Commit 281cb806 authored by Linus Torvalds's avatar Linus Torvalds

Linux-2.1.109.. preliminary code freeze.

Ok, it's out there now in all its glory...
2.1.109 does the following thing:

 - CPU detection in C code (and thus much easier to expand upon,
   especially as it's all thrown away after booting now that it is
   "initfunc()").  This should finally get the Cyrix case right, for
   example. Please test.
 - too meny people convinced me that sendfile() really wants to act like
   writep().
 - sound driver updates from Alan.
 - console updates, so now we have the full old functionality again as far
   as I'm concerned (but I'm sure people will tell me something is still
   missing)
 - task switch and user space return cleanly handles bad segment
   descriptors etc, so people shoul dno longer be able to cause kernel
   messages by misusing the LDT (and I was just informed that you could
   actually completely hang a 2.1.x SMP kernel by doing nasty things -
   this fixes it)
 - wine should work again thanks to Bill Hawes (other LDT fixes)
 - de4x5 driver update
 - token ring driver update
 - ppp driver update
 - coda-fs update
 - "shared writable" bug fixed (thanks to a lot of people for testing and
   working on this - the actual fix was trivial once the problem was
   understood)

In addition, I've spent a large part of my day running with a 12MB
machine, and low-memory behaviour seems to be reasonable. People who have
been unhappy with low-memory behaviour should check out 109 and comment on
it - the heuristics are fairly different, and seem to be better.

As of this release, I won't be looking at the "incoming" directory at the
linux-patches site any more. I'll only be looking at "urgent" things, on
the theory that I'm (a) lazy and (b) getting into code freeze.

If you have important patches in "incoming", feel free to move them to
"urgent". However, I will warn that if I don't consider them to be 2.2
material, I'll just move them to "discarded".

The same goes for patches in email. I will accept patches, but I've just
raised the bar for acception.

                Linus
parent e994d3ce
...@@ -125,6 +125,16 @@ S: 633 South 550 East ...@@ -125,6 +125,16 @@ S: 633 South 550 East
S: Provo, Utah 84606 S: Provo, Utah 84606
S: USA S: USA
M: Krzysztof G. Baranowski
E: kgb@manjak.knm.org.pl
P: 1024/FA6F16D1 96 D1 1A CF 5F CA 69 EC F9 4F 36 1F 6D 60 7B DA
D: Maintainer of the System V file system.
D: SystemV fs update for 2.1.x dcache.
D: Various bugfixes.
S: ul. Koscielna 12a
S: 62-300 Wrzesnia
S: Poland
N: Peter Bauer N: Peter Bauer
E: 100136.3530@compuserve.com E: 100136.3530@compuserve.com
D: Driver for depca-ethernet-board D: Driver for depca-ethernet-board
......
...@@ -7556,24 +7556,6 @@ CONFIG_MTRR ...@@ -7556,24 +7556,6 @@ CONFIG_MTRR
See Documentation/mtrr.txt for more information. See Documentation/mtrr.txt for more information.
Cyrix low power feature
CONFIG_CYRIX_SUSP
Cyrix 6x86 family CPUs include a feature named "Suspend on Halt".
When enabled, a single "halt" instruction puts the CPU in suspend mode
till the next interruption. In suspend mode, the CPU dissipates less
than the fiftieth of its nominal power ; the good news is that Linux
executes a halt instruction when it has nothing to, so that your CPU
will spend its idle time in suspend mode. Note that you can also
manually activate/deactivate this feature by using the set6x86 tool
available at :
ftp://tsx-11.mit.edu/pub/linux/sources/sbin/set6x86.tar.gz
There's no risk to use this. The only reason why you would say no is
if you are enough of hearing you fans changing speed because of the
difference in power consumption between idle and work time.
Please email any comments to : tarreau@aemiaif.lip6.fr
Main CPU frequency, only for DEC alpha machine Main CPU frequency, only for DEC alpha machine
CONFIG_FT_ALPHA_CLOCK CONFIG_FT_ALPHA_CLOCK
On some DEC Alpha machines the CPU clock frequency cannot be On some DEC Alpha machines the CPU clock frequency cannot be
......
...@@ -54,8 +54,7 @@ but the wavetable needs THREE! My working string is: ...@@ -54,8 +54,7 @@ but the wavetable needs THREE! My working string is:
(IO 3 (BASE 0x0E20)) (ACT Y) ))" (IO 3 (BASE 0x0E20)) (ACT Y) ))"
Resources 0x0620, 0x0A20 and 0x0E20 should work. Other on-board devices: Resources 0x0620, 0x0A20 and 0x0E20 should work. Other on-board devices:
Gameport and StereoEnhance are not needed. In my case StereoEnhance didn't Gameport and StereoEnhance are not required to be inited.
even work!
Now you can execute "isapnp /etc/isapnp.conf". No errors should be reported. Now you can execute "isapnp /etc/isapnp.conf". No errors should be reported.
If you correctly installed isapnptools, then isapnp will run every boot time. If you correctly installed isapnptools, then isapnp will run every boot time.
...@@ -64,22 +63,20 @@ If you correctly installed isapnptools, then isapnp will run every boot time. ...@@ -64,22 +63,20 @@ If you correctly installed isapnptools, then isapnp will run every boot time.
because the AWE32 driver is included in them. ATTENTION! In kernels 2.1.102, because the AWE32 driver is included in them. ATTENTION! In kernels 2.1.102,
2.1.103, 2.1.104-pre1 and 2.1.104 (not the others) the lowlevel sound driver 2.1.103, 2.1.104-pre1 and 2.1.104 (not the others) the lowlevel sound driver
is not working. You should use the patch available at is not working. You should use the patch available at
http://members.xoom.com/yar. If you are using stable kernel releases http://members.xoom.com/yar/history.html. If you are using stable kernel
2.0.x (I am not sure about 2.0.34), then get the latest version (3.8s9) of releases 2.0.x, then get the latest version (3.8s9) of
OSS/Free at http://members.xoom.com/yar/ossfree38s9-linux20x.tar.gz OSS/Free at http://members.xoom.com/yar/ossfree38s9-linux20x.tar.gz
and untar it in /usr/src/ (assuming you keep your kernel source in and gunzip/untar it in /usr/src/ (assuming you keep your kernel source in
/usr/src/linux). Then go to /usr/src/linux/ and view /usr/src/linux). Then go to /usr/src/linux/ and view the README file. That
the README file. That file contains info about kernel compilation and file contains info about kernel compilation and installation.
installation. If you use kernel version 2.0.x or version <= 2.1.104 go
to substep a, on 2.1.105 or later go to step b.
In "make (x,menu)config" select in "Sound": In "make (x,menu)config" select in "Sound":
"Sound card support", "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support", "Sound card support", "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support",
"Generic OPL2/OPL3 FM synthesizer support" and "FM synthesizer (YM3812/OPL-3) "Generic OPL2/OPL3 FM synthesizer support" and "FM synthesizer (YM3812/OPL-3)
support" as <M> (module). support" as <M> (module).
If you use kernel version 2.0.x or version <= 2.1.104 skip substep a, on If you use kernel version 2.0.x or version 2.1.y (y <= 2.1.104) skip substep a,
2.1.105 or later go through it. on 2.1.105 or later go through it.
substep a: substep a:
In "make (x,menu)config" select in "Sound": In "make (x,menu)config" select in "Sound":
...@@ -90,7 +87,7 @@ In "Additional low level sound drivers": ...@@ -90,7 +87,7 @@ In "Additional low level sound drivers":
Select "Additional low level sound drivers" as [y] (or [*] (yes)) (If it is not Select "Additional low level sound drivers" as [y] (or [*] (yes)) (If it is not
available as [y], select it as <M> (module)) available as [y], select it as <M> (module))
Now recompile the kernel (make dep; make (b)zImage; make modules; Now recompile the kernel (make dep; make (b)zImage; make modules;
make modules_install) and boot new kernel. make modules_install), update your boot loader and boot new kernel.
6) Now download awesfx program 6) Now download awesfx program
http://members.xoom.com/yar/awesfx-0.4.2.tgz here. Compile it. http://members.xoom.com/yar/awesfx-0.4.2.tgz here. Compile it.
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* *
* Enhanced CPU detection and feature setting code by Mike Jagdis * Enhanced CPU detection and feature setting code by Mike Jagdis
* and Martin Mares, November 1997, and partially recoded and moved * and Martin Mares, November 1997.
* to setup.c by Willy Tarreau, July 1998.
*/ */
.text .text
...@@ -22,9 +21,7 @@ ...@@ -22,9 +21,7 @@
#define CL_OFFSET 0x90022 #define CL_OFFSET 0x90022
/* /*
* References to members of the boot_cpu_data structure. Member * References to members of the boot_cpu_data structure.
* definitions other than X86 and X86_HARD_MATH may be removed
* since they're no more used here.
*/ */
#define CPU_PARAMS SYMBOL_NAME(boot_cpu_data) #define CPU_PARAMS SYMBOL_NAME(boot_cpu_data)
...@@ -141,13 +138,17 @@ startup_32: ...@@ -141,13 +138,17 @@ startup_32:
#ifdef __SMP__ #ifdef __SMP__
checkCPUtype: checkCPUtype:
#endif #endif
movl $-1,X86_CPUID # -1 for no CPUID initially
/* check if it is 486 or 386. */
/* /*
* check if the cpu is >=486 or <=386.
* XXX - this does a lot of unnecessary setup. Alignment checks don't * XXX - this does a lot of unnecessary setup. Alignment checks don't
* apply at our cpl of 0 and the stack ought to be aligned already, and * apply at our cpl of 0 and the stack ought to be aligned already, and
* we don't need to preserve eflags. * we don't need to preserve eflags.
*/ */
movl $3,X86 # at least 386
pushfl # push EFLAGS pushfl # push EFLAGS
popl %eax # get EFLAGS popl %eax # get EFLAGS
movl %eax,%ecx # save original EFLAGS movl %eax,%ecx # save original EFLAGS
...@@ -157,21 +158,56 @@ checkCPUtype: ...@@ -157,21 +158,56 @@ checkCPUtype:
pushfl # get new EFLAGS pushfl # get new EFLAGS
popl %eax # put it in eax popl %eax # put it in eax
xorl %ecx,%eax # change in flags xorl %ecx,%eax # change in flags
pushl %ecx # get original EFLAGS
popfl # restore EFLAGS
andl $0x40000,%eax # check if AC bit changed andl $0x40000,%eax # check if AC bit changed
movl %cr0,%eax # prepares new EAX je is386
je 1f # at most a 386
movl $4,X86 # at least 486 movl $4,X86 # at least 486
movl %ecx,%eax
xorl $0x200000,%eax # check ID flag
pushl %eax
popfl # if we are on a straight 486DX, SX, or
pushfl # 487SX we can't change it
popl %eax
xorl %ecx,%eax
pushl %ecx # restore original EFLAGS
popfl
andl $0x200000,%eax
je is486
/* get vendor info */
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
cpuid
movl %eax,X86_CPUID # save CPUID level
movl %ebx,X86_VENDOR_ID # lo 4 chars
movl %edx,X86_VENDOR_ID+4 # next 4 chars
movl %ecx,X86_VENDOR_ID+8 # last 4 chars
orl %eax,%eax # do we have processor info as well?
je is486
movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
movb %al,%cl # save reg for future use
andb $0x0f,%ah # mask processor family
movb %ah,X86
andb $0xf0,%al # mask model
shrb $4,%al
movb %al,X86_MODEL
andb $0x0f,%cl # mask mask revision
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY
is486:
movl %cr0,%eax # 486 or better
andl $0x80000011,%eax # Save PG,PE,ET andl $0x80000011,%eax # Save PG,PE,ET
orl $0x50022,%eax # set AM, WP, NE and MP orl $0x50022,%eax # set AM, WP, NE and MP
jmp 2f jmp 2f
1:
movl $3,X86 # at most 386 is386: pushl %ecx # restore original EFLAGS
popfl
movl %cr0,%eax # 386
andl $0x80000011,%eax # Save PG,PE,ET andl $0x80000011,%eax # Save PG,PE,ET
orl $2,%eax # set MP orl $2,%eax # set MP
2: movl %eax,%cr0 2: movl %eax,%cr0
call check_x87 call check_x87
#ifdef __SMP__ #ifdef __SMP__
...@@ -209,7 +245,6 @@ checkCPUtype: ...@@ -209,7 +245,6 @@ checkCPUtype:
pushl %eax pushl %eax
pushl %eax pushl %eax
cld # gcc2 wants the direction flag cleared at all times cld # gcc2 wants the direction flag cleared at all times
call SYMBOL_NAME(refine_cpu_detection) # get more info about cpu
call SYMBOL_NAME(start_kernel) call SYMBOL_NAME(start_kernel)
L6: L6:
jmp L6 # main should never return here, but jmp L6 # main should never return here, but
......
...@@ -423,6 +423,54 @@ void show_regs(struct pt_regs * regs) ...@@ -423,6 +423,54 @@ void show_regs(struct pt_regs * regs)
0xffff & regs->xds,0xffff & regs->xes); 0xffff & regs->xds,0xffff & regs->xes);
} }
/*
* Allocation and freeing of basic task resources.
*
* NOTE! The task struct and the stack go together
*
* The task structure is a two-page thing, and as such
* not reliable to allocate using the basic page alloc
* functions. We have a small cache of structures for
* when the allocations fail..
*
* This extra buffer essentially acts to make for less
* "jitter" in the allocations..
*/
#define EXTRA_TASK_STRUCT 16
static struct task_struct * task_struct_stack[EXTRA_TASK_STRUCT];
static int task_struct_stack_ptr = -1;
struct task_struct * alloc_task_struct(void)
{
int index;
struct task_struct *ret;
index = task_struct_stack_ptr;
if (index >= EXTRA_TASK_STRUCT/2)
goto use_cache;
ret = (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
if (!ret) {
index = task_struct_stack_ptr;
if (index >= 0) {
use_cache:
ret = task_struct_stack[index];
task_struct_stack_ptr = index-1;
}
}
return ret;
}
void free_task_struct(struct task_struct *p)
{
int index = task_struct_stack_ptr+1;
if (index < EXTRA_TASK_STRUCT) {
task_struct_stack[index] = p;
task_struct_stack_ptr = index;
} else
free_pages((unsigned long) p, 1);
}
void release_segments(struct mm_struct *mm) void release_segments(struct mm_struct *mm)
{ {
void * ldt = mm->segments; void * ldt = mm->segments;
......
This diff is collapsed.
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
* - making it shorter - scr_readw are macros which expand in PRETTY long code * - making it shorter - scr_readw are macros which expand in PRETTY long code
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/errno.h> #include <linux/errno.h>
......
...@@ -783,11 +783,6 @@ int parport_pc_init(int *io, int *irq, int *dma) ...@@ -783,11 +783,6 @@ int parport_pc_init(int *io, int *irq, int *dma)
count += probe_one_port(0x278, irq[0], dma[0]); count += probe_one_port(0x278, irq[0], dma[0]);
} }
/* Give any attached devices a chance to gather their thoughts */
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 75;
schedule ();
return count; return count;
} }
......
...@@ -360,9 +360,10 @@ int parport_claim(struct pardevice *dev) ...@@ -360,9 +360,10 @@ int parport_claim(struct pardevice *dev)
/* First add ourselves to the end of the wait list. */ /* First add ourselves to the end of the wait list. */
dev->waitnext = NULL; dev->waitnext = NULL;
dev->waitprev = port->waittail; dev->waitprev = port->waittail;
if (port->waittail) if (port->waittail) {
port->waittail->waitnext = dev; port->waittail->waitnext = dev;
else port->waittail = dev;
} else
port->waithead = port->waittail = dev; port->waithead = port->waittail = dev;
} }
spin_unlock_irqrestore (&port->lock, flags); spin_unlock_irqrestore (&port->lock, flags);
......
...@@ -33,7 +33,23 @@ static int rxdmacount = 0; ...@@ -33,7 +33,23 @@ static int rxdmacount = 0;
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
Lower values use more memory, but are faster. */ Lower values use more memory, but are faster. */
static int rx_copybreak = 200; /*
* NOTE! The value of 2000 means that this optimization never gets
* used. Rationale: it seems to be broken when in low-memory situations,
* apparently when alloc_skb() can return NULL the clever list of
* copy-buffers can get buggered.
*
* My personal suspicion is that the allocation failure will cause
* us to not remove the skb from the list of available buffers, but
* we'd already have done a "skb_push()" with the data we got, so
* the buffer stays on the list but the available memory in it
* shrinks until we panic.
*
* Donald, when you fix this you can shrink this value again.
*
* Linus
*/
static int rx_copybreak = 2000;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 200; static int max_interrupt_work = 200;
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#ifndef NCR53C8XX_H #ifndef NCR53C8XX_H
#define NCR53C8XX_H #define NCR53C8XX_H
#include <linux/config.h>
#if 0 #if 0
#define CONFIG_SCSI_NCR53C8XX_PROFILE #define CONFIG_SCSI_NCR53C8XX_PROFILE
#endif #endif
...@@ -62,7 +64,6 @@ ...@@ -62,7 +64,6 @@
#if !defined(LINUX_VERSION_CODE) #if !defined(LINUX_VERSION_CODE)
#include <linux/version.h> #include <linux/version.h>
#endif #endif
#include <linux/config.h>
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
......
...@@ -29,7 +29,7 @@ modules in the usual way. ...@@ -29,7 +29,7 @@ modules in the usual way.
Then, add to your /etc/modules.conf or /etc/conf.modules something like: Then, add to your /etc/modules.conf or /etc/conf.modules something like:
alias char-major-14 sb alias char-major-14 sb
post-install sb modprobe "-k" "adlib_card" post-install sb /sbin/modprobe "-k" "adlib_card"
options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
options adlib_card io=0x388 # FM synthesizer options adlib_card io=0x388 # FM synthesizer
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* *
********************************************************************/ ********************************************************************/
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/types.h> #include <linux/types.h>
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* *
********************************************************************/ ********************************************************************/
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/types.h> #include <linux/types.h>
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
* locking at some point in 2.3.x. * locking at some point in 2.3.x.
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/types.h> #include <linux/types.h>
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
* *
*/ */
#include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
......
...@@ -86,50 +86,16 @@ ...@@ -86,50 +86,16 @@
* semantics. See the comments in "open_namei" and "do_link" below. * semantics. See the comments in "open_namei" and "do_link" below.
*/ */
char * getname_quicklist = NULL;
int getname_quickcount = 0;
spinlock_t getname_quicklock = SPIN_LOCK_UNLOCKED;
/* Tuning: increase locality by reusing same pages again...
* if getname_quicklist becomes too long on low memory machines, either a limit
* should be added or after a number of cycles some pages should
* be released again ...
*/
static inline char * get_page(void) static inline char * get_page(void)
{ {
char * res; char * res;
spin_lock(&getname_quicklock);
res = getname_quicklist;
if (res) {
#ifdef DEBUG
char * tmp = res;
int i;
for(i=0; i<getname_quickcount; i++)
tmp = *(char**)tmp;
if (tmp)
printk("bad quicklist %x\n", (int)tmp);
#endif
getname_quicklist = *(char**)res;
getname_quickcount--;
}
spin_unlock(&getname_quicklock);
if (!res)
res = (char*)__get_free_page(GFP_KERNEL); res = (char*)__get_free_page(GFP_KERNEL);
return res; return res;
} }
inline void putname(char * name) inline void putname(char * name)
{ {
if (name) { free_page((unsigned long) name);
spin_lock(&getname_quicklock);
*(char**)name = getname_quicklist;
getname_quicklist = name;
getname_quickcount++;
spin_unlock(&getname_quicklock);
}
/* if a getname_quicklist limit is necessary to introduce, call
* free_page((unsigned long) name);
*/
} }
/* In order to reduce some races, while at the same time doing additional /* In order to reduce some races, while at the same time doing additional
......
...@@ -1105,6 +1105,9 @@ static int vfat_find(struct inode *dir,struct qstr* qname, ...@@ -1105,6 +1105,9 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
fil.f_pos = 0; fil.f_pos = 0;
vf.name = qname->name; vf.name = qname->name;
vf.len = qname->len; vf.len = qname->len;
while (vf.len && vf.name[vf.len-1] == '.') {
vf.len--;
}
vf.new_filename = new_filename; vf.new_filename = new_filename;
vf.found = 0; vf.found = 0;
vf.posix = MSDOS_SB(sb)->options.posixfs; vf.posix = MSDOS_SB(sb)->options.posixfs;
...@@ -1135,7 +1138,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname, ...@@ -1135,7 +1138,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
goto cleanup; goto cleanup;
} }
res = vfat_build_slots(dir, qname->name, qname->len, ds, res = vfat_build_slots(dir, qname->name, vf.len, ds,
&slots, &is_long); &slots, &is_long);
if (res < 0) goto cleanup; if (res < 0) goto cleanup;
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
* include/asm-i386/bugs.h * include/asm-i386/bugs.h
* *
* Copyright (C) 1994 Linus Torvalds * Copyright (C) 1994 Linus Torvalds
*
* Cyrix stuff, June 1998 by:
* - Rafael R. Reilova (moved everything from head.S),
* - Channing Corn (tests & fixes),
* - Andrew D. Balsa (code cleanup).
*/ */
/* /*
...@@ -226,13 +231,99 @@ __initfunc(static void check_pentium_f00f(void)) ...@@ -226,13 +231,99 @@ __initfunc(static void check_pentium_f00f(void))
} }
} }
/*
* perform the Cyrix 5/2 test (!0 means it's a Cyrix)
*/
static inline int test_cyrix_52div(void)
{
int test;
__asm__ __volatile__("xor %%eax,%%eax\n\t"
"sahf\n\t"
"movb $5,%%al\n\t"
"movb $2,%%bl\n\t"
"div %%bl\n\t"
"lahf\n\t"
"andl $0x200,%%eax": "=a" (test) : : "bx", "cc");
return test;
}
/*
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
* by the fact that they preserve the flags across the division of 5/2.
* PII and PPro exhibit this behavior too, but they have cpuid available.
*/
__initfunc(static void check_cyrix_cpu(void))
{
if (boot_cpu_data.cpuid_level == -1 && boot_cpu_data.x86 == 4
&& test_cyrix_52div()) {
/* default to an unknown Cx486, (we will diferentiate later) */
/* NOTE: using 0xff since 0x00 is a valid DIR0 value */
strcpy(boot_cpu_data.x86_vendor_id, "CyrixInstead");
boot_cpu_data.x86_model = 0xff;
boot_cpu_data.x86_mask = 0;
}
}
/*
* Fix two problems with the Cyrix 686 and 686L:
* -- the cpuid is disabled on power up, enable it, use it.
* -- the SLOP bit needs resetting on some motherboards due to old BIOS,
* so that the udelay loop calibration works well. Recalibrate.
*/
extern void calibrate_delay(void) __init;
__initfunc(static void check_cx686_cpuid_slop(void))
{
if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX &&
(boot_cpu_data.x86_model & 0xf0) == 0x30) { /* 686(L) */
int dummy;
unsigned char ccr3, ccr5;
cli();
ccr3 = getCx86(CX86_CCR3);
setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80); /* enable cpuid */
ccr5 = getCx86(CX86_CCR5);
if (ccr5 & 2) /* reset SLOP if needed, old BIOS do this wrong */
setCx86(CX86_CCR5, ccr5 & 0xfd);
setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
sti();
boot_cpu_data.cpuid_level = 1; /* should cover all 6x86(L) */
boot_cpu_data.x86 = 5;
/* we know we have level 1 available on the 6x86(L) */
cpuid(1, &dummy, &dummy, &dummy,
&boot_cpu_data.x86_capability);
/*
* DON'T use the x86_mask and x86_model from cpuid, these are
* not as accurate (or the same) as those from the DIR regs.
* already in place after cyrix_model() in setup.c
*/
if (ccr5 & 2) { /* possible wrong calibration done */
printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
calibrate_delay();
boot_cpu_data.loops_per_sec = loops_per_sec;
}
}
}
__initfunc(static void check_bugs(void)) __initfunc(static void check_bugs(void))
{ {
check_cyrix_cpu();
identify_cpu(&boot_cpu_data); identify_cpu(&boot_cpu_data);
#ifndef __SMP__ #ifndef __SMP__
printk("CPU: "); printk("CPU: ");
print_cpu_info(&boot_cpu_data); print_cpu_info(&boot_cpu_data);
#endif #endif
check_cx686_cpuid_slop();
check_tlb(); check_tlb();
check_fpu(); check_fpu();
check_hlt(); check_hlt();
......
...@@ -99,6 +99,51 @@ extern char ignore_irq13; ...@@ -99,6 +99,51 @@ extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *); extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *);
/*
* Generic CPUID function
*/
extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
{
__asm__("cpuid"
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (op)
: "cc");
}
/*
* Cyrix CPU configuration register indexes
*/
#define CX86_CCR2 0xc2
#define CX86_CCR3 0xc3
#define CX86_CCR4 0xe8
#define CX86_CCR5 0xe9
#define CX86_DIR0 0xfe
#define CX86_DIR1 0xff
/*
* Cyrix CPU indexed register access macros
*/
extern inline unsigned char getCx86(unsigned char reg)
{
unsigned char data;
__asm__ __volatile__("movb %1,%%al\n\t"
"outb %%al,$0x22\n\t"
"inb $0x23,%%al" : "=a" (data) : "q" (reg));
return data;
}
extern inline void setCx86(unsigned char reg, unsigned char data)
{
__asm__ __volatile__("outb %%al,$0x22\n\t"
"movb %1,%%al\n\t"
"outb %%al,$0x23" : : "a" (reg), "q" (data));
}
/* /*
* Bus types (default is ISA, but people can check others with these..) * Bus types (default is ISA, but people can check others with these..)
*/ */
...@@ -248,13 +293,8 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t) ...@@ -248,13 +293,8 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t)
return ((unsigned long *)t->esp)[3]; return ((unsigned long *)t->esp)[3];
} }
/* Allocation and freeing of basic task resources. */ extern struct task_struct * alloc_task_struct(void);
/* extern void free_task_struct(struct task_struct *);
* NOTE! The task struct and the stack go together
*/
#define alloc_task_struct() \
((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
#define free_task_struct(p) free_pages((unsigned long)(p),1)
#define init_task (init_task_union.task) #define init_task (init_task_union.task)
#define init_stack (init_task_union.stack) #define init_stack (init_task_union.stack)
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
*/ */
#define CUR_DEFAULT CUR_UNDERLINE #define CUR_DEFAULT CUR_UNDERLINE
#include <linux/config.h>
#define NPAR 16 #define NPAR 16
struct vc_data { struct vc_data {
......
...@@ -254,21 +254,9 @@ extern inline unsigned long get_free_page(int gfp_mask) ...@@ -254,21 +254,9 @@ extern inline unsigned long get_free_page(int gfp_mask)
/* memory.c & swap.c*/ /* memory.c & swap.c*/
/* /*
* This traverses "nr" memory size lists, * Decide if we should try to do some swapout..
* and returns true if there is enough memory.
*
* For example, we want to keep on waking up
* kswapd every once in a while until the highest
* memory order has an entry (ie nr == 0), but
* we want to do it in the background.
*
* We want to do it in the foreground only if
* none of the three highest lists have enough
* memory. Random number.
*/ */
extern int free_memory_available(int nr); extern int free_memory_available(void);
#define kswapd_continue() (!free_memory_available(3))
#define kswapd_wakeup() (!free_memory_available(0))
#define free_page(addr) free_pages((addr),0) #define free_page(addr) free_pages((addr),0)
extern void FASTCALL(free_pages(unsigned long addr, unsigned long order)); extern void FASTCALL(free_pages(unsigned long addr, unsigned long order));
...@@ -330,8 +318,8 @@ extern void put_cached_page(unsigned long); ...@@ -330,8 +318,8 @@ extern void put_cached_page(unsigned long);
#define GFP_BUFFER (__GFP_LOW | __GFP_WAIT) #define GFP_BUFFER (__GFP_LOW | __GFP_WAIT)
#define GFP_ATOMIC (__GFP_HIGH) #define GFP_ATOMIC (__GFP_HIGH)
#define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO) #define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO)
#define GFP_KERNEL (__GFP_LOW | __GFP_WAIT | __GFP_IO) #define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO)
#define GFP_NFS (__GFP_MED | __GFP_WAIT | __GFP_IO) #define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
platforms, used as appropriate on others */ platforms, used as appropriate on others */
......
...@@ -50,7 +50,7 @@ struct sysinfo; ...@@ -50,7 +50,7 @@ struct sysinfo;
extern int shm_swap (int, int); extern int shm_swap (int, int);
/* linux/mm/vmscan.c */ /* linux/mm/vmscan.c */
extern int try_to_free_page(int); extern int try_to_free_pages(unsigned int gfp_mask, int count);
/* linux/mm/page_io.c */ /* linux/mm/page_io.c */
extern void rw_swap_page(int, unsigned long, char *, int); extern void rw_swap_page(int, unsigned long, char *, int);
...@@ -128,21 +128,6 @@ static inline int is_page_shared(struct page *page) ...@@ -128,21 +128,6 @@ static inline int is_page_shared(struct page *page)
return (count > 1); return (count > 1);
} }
/*
* When we're freeing pages from a user application, we want
* to cluster swapouts too. -- Rik.
* linux/mm/page_alloc.c
*/
static inline int try_to_free_pages(int gfp_mask, int count)
{
int retval = 0;
while (count--) {
if (try_to_free_page(gfp_mask))
retval = 1;
}
return retval;
}
/* /*
* Make these inline later once they are working properly. * Make these inline later once they are working properly.
*/ */
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_VGA_CONSOLE #ifdef CONFIG_VGA_CONSOLE
#ifndef CONFIG_FB_MODULE #if !defined(CONFIG_FB) && !defined(CONFIG_FB_MODULE)
#define VT_BUF_VRAM_ONLY #define VT_BUF_VRAM_ONLY
#endif #endif
#include <asm/vga.h> #include <asm/vga.h>
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* with information needed by the vt package * with information needed by the vt package
*/ */
#include <linux/config.h>
#include <linux/vt.h> #include <linux/vt.h>
/* /*
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
modprobe_path is set via /proc/sys. modprobe_path is set via /proc/sys.
*/ */
char modprobe_path[256] = "/sbin/modprobe"; char modprobe_path[256] = "/sbin/modprobe";
static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
/* /*
exec_modprobe is spawned from a kernel-mode user process, exec_modprobe is spawned from a kernel-mode user process,
......
...@@ -125,8 +125,8 @@ int shrink_mmap(int priority, int gfp_mask) ...@@ -125,8 +125,8 @@ int shrink_mmap(int priority, int gfp_mask)
struct buffer_head *tmp, *bh; struct buffer_head *tmp, *bh;
int count_max, count_min; int count_max, count_min;
count_max = (limit<<1) >> (priority>>1); count_max = (limit<<2) >> (priority>>1);
count_min = (limit<<1) >> (priority); count_min = (limit<<2) >> (priority);
page = mem_map + clock; page = mem_map + clock;
do { do {
......
...@@ -57,19 +57,19 @@ int vm_enough_memory(long pages) ...@@ -57,19 +57,19 @@ int vm_enough_memory(long pages)
* simple, it hopefully works in most obvious cases.. Easy to * simple, it hopefully works in most obvious cases.. Easy to
* fool it, but this should catch most mistakes. * fool it, but this should catch most mistakes.
*/ */
long freepages; long free;
/* Sometimes we want to use more memory than we have. */ /* Sometimes we want to use more memory than we have. */
if (sysctl_overcommit_memory) if (sysctl_overcommit_memory)
return 1; return 1;
freepages = buffermem >> PAGE_SHIFT; free = buffermem >> PAGE_SHIFT;
freepages += page_cache_size; free += page_cache_size;
freepages >>= 1; free >>= 1;
freepages += nr_free_pages; free += nr_free_pages;
freepages += nr_swap_pages; free += nr_swap_pages;
freepages -= num_physpages >> 4; free -= num_physpages >> 4;
return freepages > pages; return free > pages;
} }
/* Remove one vm structure from the inode's i_mmap ring. */ /* Remove one vm structure from the inode's i_mmap ring. */
......
...@@ -103,48 +103,28 @@ spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; ...@@ -103,48 +103,28 @@ spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
/* /*
* This routine is used by the kernel swap daemon to determine * This routine is used by the kernel swap daemon to determine
* whether we have "enough" free pages. It is fairly arbitrary, * whether we have "enough" free pages. It is fairly arbitrary,
* but this had better return false if any reasonable "get_free_page()" * having a low-water and high-water mark.
* allocation could currently fail..
* *
* This will return zero if no list was found, non-zero * This returns:
* if there was memory (the bigger, the better). * 0 - urgent need for memory
* 1 - need some memory, but do it slowly in the background
* 2 - no need to even think about it.
*/ */
int free_memory_available(int nr) int free_memory_available(void)
{ {
int retval = 0; static int available = 1;
unsigned long flags;
struct free_area_struct * list;
/* if (nr_free_pages < freepages.low) {
* If we have more than about 3% to 5% of all memory free, available = 0;
* consider it to be good enough for anything. return 0;
* It may not be, due to fragmentation, but we }
* don't want to keep on forever trying to find
* free unfragmented memory.
* Added low/high water marks to avoid thrashing -- Rik.
*/
if (nr_free_pages > (nr ? freepages.low : freepages.high))
return nr+1;
list = free_area + NR_MEM_LISTS; if (nr_free_pages > freepages.high) {
spin_lock_irqsave(&page_alloc_lock, flags); available = 1;
/* We fall through the loop if the list contains one return 2;
* item. -- thanks to Colin Plumb <colin@nyx.net> }
*/
do { return available;
list--;
/* Empty list? Bad - we need more memory */
if (list->next == memory_head(list))
break;
/* One item on the list? Look further */
if (list->next->next == memory_head(list))
continue;
/* More than one item? We're ok */
retval = nr + 1;
break;
} while (--nr >= 0);
spin_unlock_irqrestore(&page_alloc_lock, flags);
return retval;
} }
static inline void free_pages_ok(unsigned long map_nr, unsigned long order) static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
...@@ -217,13 +197,11 @@ void free_pages(unsigned long addr, unsigned long order) ...@@ -217,13 +197,11 @@ void free_pages(unsigned long addr, unsigned long order)
change_bit((index) >> (1+(order)), (area)->map) change_bit((index) >> (1+(order)), (area)->map)
#define CAN_DMA(x) (PageDMA(x)) #define CAN_DMA(x) (PageDMA(x))
#define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT)) #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
#define RMQUEUE(order, maxorder, dma) \ #define RMQUEUE(order, dma) \
do { struct free_area_struct * area = free_area+order; \ do { struct free_area_struct * area = free_area+order; \
unsigned long new_order = order; \ unsigned long new_order = order; \
do { struct page *prev = memory_head(area), *ret = prev->next; \ do { struct page *prev = memory_head(area), *ret = prev->next; \
while (memory_head(area) != ret) { \ while (memory_head(area) != ret) { \
if (new_order >= maxorder && ret->next == prev) \
break; \
if (!dma || CAN_DMA(ret)) { \ if (!dma || CAN_DMA(ret)) { \
unsigned long map_nr = ret->map_nr; \ unsigned long map_nr = ret->map_nr; \
(prev->next = ret->next)->prev = prev; \ (prev->next = ret->next)->prev = prev; \
...@@ -255,39 +233,36 @@ do { unsigned long size = 1 << high; \ ...@@ -255,39 +233,36 @@ do { unsigned long size = 1 << high; \
unsigned long __get_free_pages(int gfp_mask, unsigned long order) unsigned long __get_free_pages(int gfp_mask, unsigned long order)
{ {
unsigned long flags, maxorder; unsigned long flags;
if (order >= NR_MEM_LISTS) if (order >= NR_MEM_LISTS)
goto nopage; goto nopage;
/* if (gfp_mask & __GFP_WAIT) {
* "maxorder" is the highest order number that we're allowed if (in_interrupt()) {
* to empty in order to find a free page..
*/
maxorder = NR_MEM_LISTS-1;
if (gfp_mask & __GFP_HIGH)
maxorder = NR_MEM_LISTS;
if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
static int count = 0; static int count = 0;
if (++count < 5) { if (++count < 5) {
printk("gfp called nonatomically from interrupt %p\n", printk("gfp called nonatomically from interrupt %p\n",
__builtin_return_address(0)); __builtin_return_address(0));
gfp_mask &= ~__GFP_WAIT;
} }
goto nopage;
} }
for (;;) { if (freepages.min > nr_free_pages) {
int freed;
freed = try_to_free_pages(gfp_mask, SWAP_CLUSTER_MAX);
/*
* Low priority (user) allocations must not
* succeed if we didn't have enough memory
* and we couldn't get more..
*/
if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
goto nopage;
}
}
spin_lock_irqsave(&page_alloc_lock, flags); spin_lock_irqsave(&page_alloc_lock, flags);
RMQUEUE(order, maxorder, (gfp_mask & GFP_DMA)); RMQUEUE(order, (gfp_mask & GFP_DMA));
spin_unlock_irqrestore(&page_alloc_lock, flags); spin_unlock_irqrestore(&page_alloc_lock, flags);
if (!(gfp_mask & __GFP_WAIT))
break;
if (!try_to_free_pages(gfp_mask, SWAP_CLUSTER_MAX))
break;
gfp_mask &= ~__GFP_WAIT; /* go through this only once */
maxorder = NR_MEM_LISTS; /* Allow anything this time */
}
nopage: nopage:
return 0; return 0;
} }
...@@ -303,6 +278,11 @@ void show_free_areas(void) ...@@ -303,6 +278,11 @@ void show_free_areas(void)
unsigned long total = 0; unsigned long total = 0;
printk("Free pages: %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10)); printk("Free pages: %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10));
printk("Free: %d (%d %d %d)\n",
nr_free_pages,
freepages.min,
freepages.low,
freepages.high);
spin_lock_irqsave(&page_alloc_lock, flags); spin_lock_irqsave(&page_alloc_lock, flags);
for (order=0 ; order < NR_MEM_LISTS; order++) { for (order=0 ; order < NR_MEM_LISTS; order++) {
struct page * tmp; struct page * tmp;
......
...@@ -444,7 +444,7 @@ static int swap_out(unsigned int priority, int gfp_mask) ...@@ -444,7 +444,7 @@ static int swap_out(unsigned int priority, int gfp_mask)
* to be. This works out OK, because we now do proper aging on page * to be. This works out OK, because we now do proper aging on page
* contents. * contents.
*/ */
static inline int do_try_to_free_page(int gfp_mask) static int do_try_to_free_page(int gfp_mask)
{ {
static int state = 0; static int state = 0;
int i=6; int i=6;
...@@ -457,9 +457,10 @@ static inline int do_try_to_free_page(int gfp_mask) ...@@ -457,9 +457,10 @@ static inline int do_try_to_free_page(int gfp_mask)
stop = 3; stop = 3;
if (gfp_mask & __GFP_WAIT) if (gfp_mask & __GFP_WAIT)
stop = 0; stop = 0;
if (((buffermem >> PAGE_SHIFT) * 100 > buffer_mem.borrow_percent * num_physpages) if (((buffermem >> PAGE_SHIFT) * 100 > buffer_mem.borrow_percent * num_physpages)
|| (page_cache_size * 100 > page_cache.borrow_percent * num_physpages)) || (page_cache_size * 100 > page_cache.borrow_percent * num_physpages))
state = 0; shrink_mmap(i, gfp_mask);
switch (state) { switch (state) {
do { do {
...@@ -484,23 +485,6 @@ static inline int do_try_to_free_page(int gfp_mask) ...@@ -484,23 +485,6 @@ static inline int do_try_to_free_page(int gfp_mask)
return 0; return 0;
} }
/*
* This is REALLY ugly.
*
* We need to make the locks finer granularity, but right
* now we need this so that we can do page allocations
* without holding the kernel lock etc.
*/
int try_to_free_page(int gfp_mask)
{
int retval;
lock_kernel();
retval = do_try_to_free_page(gfp_mask);
unlock_kernel();
return retval;
}
/* /*
* Before we start the kernel thread, print out the * Before we start the kernel thread, print out the
* kswapd initialization message (otherwise the init message * kswapd initialization message (otherwise the init message
...@@ -573,15 +557,16 @@ int kswapd(void *unused) ...@@ -573,15 +557,16 @@ int kswapd(void *unused)
* woken up more often and the rate will be even * woken up more often and the rate will be even
* higher). * higher).
*/ */
tries = pager_daemon.tries_base >> free_memory_available(3); tries = pager_daemon.tries_base;
tries >>= 4*free_memory_available();
while (tries--) { while (tries--) {
int gfp_mask; int gfp_mask;
if (++tried > pager_daemon.tries_min && free_memory_available(0)) if (free_memory_available() > 1)
break; break;
gfp_mask = __GFP_IO; gfp_mask = __GFP_IO;
try_to_free_page(gfp_mask); do_try_to_free_page(gfp_mask);
/* /*
* Syncing large chunks is faster than swapping * Syncing large chunks is faster than swapping
* synchronously (less head movement). -- Rik. * synchronously (less head movement). -- Rik.
...@@ -597,6 +582,27 @@ int kswapd(void *unused) ...@@ -597,6 +582,27 @@ int kswapd(void *unused)
return 0; return 0;
} }
/*
* This is REALLY ugly.
*
* We need to make the locks finer granularity, but right
* now we need this so that we can do page allocations
* without holding the kernel lock etc.
*/
int try_to_free_pages(unsigned int gfp_mask, int count)
{
int retval;
lock_kernel();
retval = 0;
do {
retval |= do_try_to_free_page(gfp_mask);
count--;
} while (count > 0);
unlock_kernel();
return retval;
}
/* /*
* The swap_tick function gets called on every clock tick. * The swap_tick function gets called on every clock tick.
*/ */
...@@ -616,11 +622,11 @@ void swap_tick(void) ...@@ -616,11 +622,11 @@ void swap_tick(void)
* Schedule for wakeup if there isn't lots * Schedule for wakeup if there isn't lots
* of free memory. * of free memory.
*/ */
switch (free_memory_available(3)) { switch (free_memory_available()) {
case 0: case 0:
want = now; want = now;
/* Fall through */ /* Fall through */
case 1 ... 3: case 1:
want_wakeup = 1; want_wakeup = 1;
default: default:
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment