All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Richard Henderson <rth@twiddle.net>,
	Jay Estabrook <Jay.Estabrook@compaq.com>,
	andrea@suse.de, frival@zk3.dec.com, linux-kernel@vger.kernel.org,
	mingo@redhat.com
Subject: Re: Alpha update for 2.5.3
Date: Thu, 7 Feb 2002 16:59:49 -0800	[thread overview]
Message-ID: <20020207165949.A3759@are.twiddle.net> (raw)
In-Reply-To: <20020207211329.A861@jurassic.park.msu.ru>
In-Reply-To: <20020207211329.A861@jurassic.park.msu.ru>; from ink@jurassic.park.msu.ru on Thu, Feb 07, 2002 at 09:13:29PM +0300

[-- Attachment #1: Type: text/plain, Size: 1495 bytes --]

I guess I should have posted my incomplete patches instead of
making you duplicate effort.

On Thu, Feb 07, 2002 at 09:13:29PM +0300, Ivan Kokshaysky wrote:
> - new block layer
>   minor changes here - new BIO_VMERGE_BOUNDARY macro,
>   which hints to BIO that we're able to merge segments on the page
>   boundary;
>   max_pfn = max_low_pfn indicates that we don't need bounce buffers;

This isn't complete.  I suspect either (1) I'm missing something
fundamental or (2) this code is.  It appears to make fundamental
assumptions about "isa" and "low memory" that are not necessarily
correct on non-peecees.

In addition to your bits, I needed to hack ll_rw_blk in order to
boot from an aic7xxx.

> - new scheduler
>   [as usual, untested on SMP - anybody willing to give it a try? Peter?]

The following does *not* work on SMP.  CPU1 segfaults because 
context_switch is called with next=NULL.  I've not yet figured
out what I'm missing in the smp setup.  Ingo, is there anything
obvious?

>   new smp_migrate_task IPI; more or less obvious compile fixes.

Given the nature of the ipi, I prefer to streamline this
particular cross-call like so.

> - syscall "optimization"
>   several fields of task_struct have been squeezed to bytes,
>   so this required byte `xchg' - fortunately my old patch for
>   8 and 16 bit atomic `xchg' came in handy. :-)

Nope.  The xchg thing no longer works.  Look at the x86 code.

Your xchg hack is still cool, and should go in, but it is not
needed here.


r~

[-- Attachment #2: d-axp-20020207 --]
[-- Type: text/plain, Size: 34864 bytes --]

diff -ruNp linux/arch/alpha/Makefile 2.5.3/arch/alpha/Makefile
--- linux/arch/alpha/Makefile	Sun Dec  3 17:45:20 2000
+++ 2.5.3/arch/alpha/Makefile	Sat Feb  2 16:32:39 2002
@@ -117,11 +117,13 @@ srmboot:
 archclean:
 	@$(MAKE) -C arch/alpha/kernel clean
 	@$(MAKEBOOT) clean
-	rm -f arch/alpha/vmlinux.lds
 
 archmrproper:
+	rm -f arch/alpha/vmlinux.lds
+	rm -f include/asm-alpha/asm_offsets.h
 
 archdep:
+	$(MAKE) -C arch/alpha/kernel asm_offsets
 	@$(MAKEBOOT) dep
 
 vmlinux: arch/alpha/vmlinux.lds
diff -ruNp linux/arch/alpha/kernel/Makefile 2.5.3/arch/alpha/kernel/Makefile
--- linux/arch/alpha/kernel/Makefile	Sun Aug 12 10:51:41 2001
+++ 2.5.3/arch/alpha/kernel/Makefile	Sat Feb  2 15:29:33 2002
@@ -8,9 +8,9 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 .S.s:
-	$(CPP) $(AFLAGS) -o $*.s $<
+	$(CPP) $(CFLAGS) $(AFLAGS) -o $*.s $<
 .S.o:
-	$(CC) $(AFLAGS) -c -o $*.o $<
+	$(CC) $(CFLAGS) $(AFLAGS) -c -o $*.o $<
 
 O_TARGET := kernel.o
 
@@ -102,11 +102,15 @@ endif # GENERIC
 
 all: kernel.o head.o
 
-asm_offsets: check_asm
-	./check_asm > $(TOPDIR)/include/asm-alpha/asm_offsets.h
-
-check_asm: check_asm.c
-	$(HOSTCC) -o $@ $< $(CPPFLAGS) -ffixed-8
+ASM_OFFSETS_H = $(TOPDIR)/include/asm-alpha/asm_offsets.h
+asm_offsets:
+	$(CC) $(CFLAGS) -S -o - check_asm.c | \
+	sed -e '/xyzzy/ { s/xyzzy //; p; }; d;' > asm_offsets.tmp
+	@if cmp -s asm_offsets.tmp $(ASM_OFFSETS_H); then \
+	  set -x; rm asm_offsets.tmp; \
+	else \
+	  set -x; mv asm_offsets.tmp $(ASM_OFFSETS_H); \
+	fi
 
 clean::
 	rm -f check_asm
diff -ruNp linux/arch/alpha/kernel/check_asm.c 2.5.3/arch/alpha/kernel/check_asm.c
--- linux/arch/alpha/kernel/check_asm.c	Mon Jan 28 15:14:22 2002
+++ 2.5.3/arch/alpha/kernel/check_asm.c	Sat Feb  2 15:27:37 2002
@@ -3,30 +3,38 @@
 #include <linux/sched.h>
 #include <asm/io.h>
 
-int main()
+#define OUT(x) \
+  asm ("\nxyzzy " x)
+#define DEF(name, val) \
+  asm volatile ("\nxyzzy #define " name " %0" : : "i"(val))
+
+void foo(void)
 {
-	printf("#ifndef __ASM_OFFSETS_H__\n#define __ASM_OFFSETS_H__\n");
+	OUT("#ifndef __ASM_OFFSETS_H__");
+	OUT("#define __ASM_OFFSETS_H__");
+	OUT("");
 
-	printf("#define TASK_STATE %ld\n",
-	       (long)offsetof(struct task_struct, state));
-	printf("#define TASK_FLAGS %ld\n",
-	       (long)offsetof(struct task_struct, flags));
-	printf("#define TASK_SIGPENDING %ld\n",
-#error	       (long)offsetof(struct task_struct, sigpending));
-	printf("#define TASK_ADDR_LIMIT %ld\n",
-	       (long)offsetof(struct task_struct, addr_limit));
-	printf("#define TASK_EXEC_DOMAIN %ld\n",
-	       (long)offsetof(struct task_struct, exec_domain));
-	printf("#define TASK_NEED_RESCHED %ld\n",
-#error	       (long)offsetof(struct task_struct, work.need_resched));
-	printf("#define TASK_SIZE %ld\n", sizeof(struct task_struct));
-	printf("#define STACK_SIZE %ld\n", sizeof(union task_union));
+	DEF("TASK_STATE", offsetof(struct task_struct, state));
+	DEF("TASK_FLAGS", offsetof(struct task_struct, flags));
+	DEF("TASK_WORK", offsetof(struct task_struct, work));
+	DEF("TASK_WORK_NEED_RESCHED",
+	    offsetof(struct task_struct, work.need_resched));
+	DEF("TASK_WORK_SYSCALL_TRACE",
+	    offsetof(struct task_struct, work.syscall_trace));
+	DEF("TASK_WORK_SIGPENDING",
+	    offsetof(struct task_struct, work.sigpending));
+	DEF("TASK_ADDR_LIMIT", offsetof(struct task_struct, addr_limit));
+	DEF("TASK_EXEC_DOMAIN", offsetof(struct task_struct, exec_domain));
+	DEF("TASK_PTRACE", offsetof(struct task_struct, ptrace));
+	DEF("TASK_SIZE", sizeof(struct task_struct));
+	DEF("STACK_SIZE", sizeof(union task_union));
+	DEF("PT_PTRACED", PT_PTRACED);
+	DEF("CLONE_VM", CLONE_VM);
+	DEF("SIGCHLD", SIGCHLD);
 
-	printf("#define HAE_CACHE %ld\n",
-	       (long)offsetof(struct alpha_machine_vector, hae_cache));
-	printf("#define HAE_REG %ld\n",
-	       (long)offsetof(struct alpha_machine_vector, hae_register));
+	DEF("HAE_CACHE", offsetof(struct alpha_machine_vector, hae_cache));
+	DEF("HAE_REG", offsetof(struct alpha_machine_vector, hae_register));
 
-	printf("#endif /* __ASM_OFFSETS_H__ */\n");
-	return 0;
+	OUT("");
+	OUT("#endif /* __ASM_OFFSETS_H__ */");
 }
diff -ruNp linux/arch/alpha/kernel/entry.S 2.5.3/arch/alpha/kernel/entry.S
--- linux/arch/alpha/kernel/entry.S	Mon Jan 28 15:14:22 2002
+++ 2.5.3/arch/alpha/kernel/entry.S	Sat Feb  2 15:27:37 2002
@@ -7,42 +7,15 @@
 #include <linux/config.h>
 #include <asm/system.h>
 #include <asm/cache.h>
-
-#define SIGCHLD 20
+#include <asm/asm_offsets.h>
 
 #define NR_SYSCALLS 378
 
 /*
- * These offsets must match with alpha_mv in <asm/machvec.h>.
- */
-#define HAE_CACHE	0
-#define HAE_REG		8
-
-/*
  * stack offsets
  */
-#define SP_OFF		184
-
-#define SWITCH_STACK_SIZE 320
-
-/*
- * task structure offsets
- */
-#define TASK_STATE		0
-#define TASK_FLAGS		8
-#error #define TASK_SIGPENDING		16
-#define TASK_ADDR_LIMIT		24
-#define TASK_EXEC_DOMAIN	32
-#error #define TASK_NEED_RESCHED	40
-#error #define TASK_PTRACE		48
-#define TASK_PROCESSOR		100
-
-/*
- * task flags (must match include/linux/sched.h):
- */
-#define	PT_PTRACED	0x00000001
-
-#define CLONE_VM        0x00000100 
+#define SP_OFF			184
+#define SWITCH_STACK_SIZE	320
 
 /*
  * This defines the normal kernel pt-regs layout.
@@ -121,9 +94,6 @@
 
 .text
 .set noat
-#if defined(__linux__) && !defined(__ELF__)
-  .set singlegp
-#endif
 
 .align 3
 .globl	entInt
@@ -559,10 +529,14 @@ entSys:
 	lda	$5,sys_call_table
 	lda	$27,sys_ni_syscall
 	cmpult	$0,$4,$4
-	ldq	$3,TASK_PTRACE($8)
+#ifdef __alpha_bwx__
+	ldbu	$3,TASK_WORK_SYSCALL_TRACE($8)
+#else
+	ldl	$3,TASK_WORK($8)
+	extbl	$3,TASK_WORK_SYSCALL_TRACE,$3
+#endif
 	stq	$17,SP_OFF+32($30)
 	s8addq	$0,$5,$5
-	and     $3,PT_PTRACED,$3
 	stq	$18,SP_OFF+40($30)
 	bne     $3,strace
 	beq	$4,1f
@@ -579,18 +553,47 @@ ret_from_sys_call:
 	ldq	$0,SP_OFF($30)
 	and	$0,8,$0
 	beq	$0,restore_all
-ret_from_reschedule:
-#error	ldq	$2,TASK_NEED_RESCHED($8)
-	lda	$4,init_task_union
-	bne	$2,reschedule
-	xor	$4,$8,$4
-#error	ldl	$5,TASK_SIGPENDING($8)
-	beq	$4,restore_all
-	bne	$5,signal_return
+	/* Make sure need_resched and sigpending don't change between
+	   sampling and the rti.  */
+	lda	$16,7
+	call_pal PAL_swpipl
+	ldl	$5,TASK_WORK($8)
+	zapnot	$5,0x0D,$5		/* clear syscall trace counter  */
+	bne	$5,work_pending
 restore_all:
 	RESTORE_ALL
 	call_pal PAL_rti
 
+.align 3
+work_pending:
+	extbl	$5,TASK_WORK_NEED_RESCHED,$2
+	beq	$2,work_notifysig
+
+	subq	$30,16,$30
+	stq	$19,0($30)		/* save syscall nr */
+	stq	$20,8($30)		/* and error indication (a3) */
+	jsr	$26,schedule
+	ldq	$19,0($30)
+	ldq	$20,8($30)
+	addq	$30,16,$30
+	/* Make sure need_resched and sigpending don't change between
+	   sampling and the rti.  */
+	lda	$16,7
+	call_pal PAL_swpipl
+	ldl	$5,TASK_WORK($8)
+	zapnot	$5,0x0D,$5		/* clear syscall trace counter  */
+	bne	$5,work_pending
+
+work_notifysig:
+	extbl	$5,TASK_WORK_SIGPENDING,$2
+	beq	$2,restore_all
+	mov	$30,$17
+	br	$1,do_switch_stack
+	mov	$30,$18
+	mov	$31,$16
+	jsr	$26,do_signal
+	bsr	$1,undo_switch_stack
+	br	restore_all
 
 /* PTRACE syscall handler */
 .align 3
@@ -677,16 +680,6 @@ ret_success:
 	stq	$0,0($30)
 	stq	$31,72($30)	/* a3=0 => no error */
 	br	ret_from_sys_call
-
-.align 3
-signal_return:
-	mov	$30,$17
-	br	$1,do_switch_stack
-	mov	$30,$18
-	mov	$31,$16
-	jsr	$26,do_signal
-	bsr	$1,undo_switch_stack
-	br	restore_all
 .end entSys
 
         .globl  ret_from_fork
@@ -697,19 +690,6 @@ ret_from_fork:
 	mov	$17,$16
 	jsr	$31,schedule_tail
 .end ret_from_fork
-
-.align 3
-.ent reschedule
-reschedule:
-	subq	$30,16,$30
-	stq	$19,0($30)	/* save syscall nr */
-	stq	$20,8($30)	/* and error indication (a3) */
-	jsr	$26,schedule
-	ldq	$19,0($30)
-	ldq	$20,8($30)
-	addq	$30,16,$30
-	br	ret_from_reschedule
-.end reschedule
 
 .align 3
 .ent sys_sigreturn
diff -ruNp linux/arch/alpha/kernel/process.c 2.5.3/arch/alpha/kernel/process.c
--- linux/arch/alpha/kernel/process.c	Mon Jan 28 15:14:22 2002
+++ 2.5.3/arch/alpha/kernel/process.c	Sat Feb  2 14:51:47 2002
@@ -30,6 +30,7 @@
 #include <linux/reboot.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/init_task.h>
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
@@ -74,17 +75,12 @@ void
 cpu_idle(void)
 {
 	/* An endless idle loop with no priority at all.  */
-	current->nice = 20;
-
 	while (1) {
 		/* FIXME -- EV6 and LCA45 know how to power down
 		   the CPU.  */
 
-		/* Although we are an idle CPU, we do not want to 
-		   get into the scheduler unnecessarily.  */
-		long oldval = xchg(&current->work.need_resched, -1UL);
-		if (!oldval)
-			while (current->work.need_resched < 0);
+		while (! need_resched())
+			barrier();
 		schedule();
 		check_pgt_cache();
 	}
diff -ruNp linux/arch/alpha/kernel/ptrace.c 2.5.3/arch/alpha/kernel/ptrace.c
--- linux/arch/alpha/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
+++ 2.5.3/arch/alpha/kernel/ptrace.c	Sat Feb  2 15:27:37 2002
@@ -334,10 +334,17 @@ sys_ptrace(long request, long pid, long 
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			goto out;
-		if (request == PTRACE_SYSCALL)
-			child->ptrace |= PT_TRACESYS;
-		else
-			child->ptrace &= ~PT_TRACESYS;
+		if (request == PTRACE_SYSCALL) {
+			if (!(child->ptrace & PT_SYSCALLTRACE)) {
+				child->ptrace |= PT_SYSCALLTRACE;
+				child->work.syscall_trace++;
+			}
+		} else {
+			if (child->ptrace & PT_SYSCALLTRACE) {
+				child->ptrace &= ~PT_SYSCALLTRACE;
+				child->work.syscall_trace--;
+			}
+		}
 		child->exit_code = data;
 		wake_up_process(child);
 		/* make sure single-step breakpoint is gone. */
@@ -365,7 +372,10 @@ sys_ptrace(long request, long pid, long 
 		if ((unsigned long) data > _NSIG)
 			goto out;
 		child->thread.bpt_nsaved = -1;	/* mark single-stepping */
-		child->ptrace &= ~PT_TRACESYS;
+		if (child->ptrace & PT_SYSCALLTRACE) {
+			child->ptrace &= ~PT_SYSCALLTRACE;
+			child->work.syscall_trace--;
+		}
 		wake_up_process(child);
 		child->exit_code = data;
 		/* give it a chance to run. */
@@ -390,8 +400,8 @@ sys_ptrace(long request, long pid, long 
 asmlinkage void
 syscall_trace(void)
 {
-	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
-	    != (PT_PTRACED|PT_TRACESYS))
+	if ((current->ptrace & (PT_PTRACED|PT_SYSCALLTRACE))
+	    != (PT_PTRACED|PT_SYSCALLTRACE))
 		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
diff -ruNp linux/arch/alpha/kernel/setup.c 2.5.3/arch/alpha/kernel/setup.c
--- linux/arch/alpha/kernel/setup.c	Tue Dec 25 15:39:20 2001
+++ 2.5.3/arch/alpha/kernel/setup.c	Thu Feb  7 15:25:40 2002
@@ -68,7 +68,7 @@ int boot_cpuid;
  * Using SRM callbacks for initial console output. This works from
  * setup_arch() time through the end of time_init(), as those places
  * are under our (Alpha) control.
-
+ *
  * "srmcons" specified in the boot command arguments allows us to
  * see kernel messages during the period of time before the true
  * console device is "registered" during console_init(). As of this
@@ -436,8 +436,8 @@ static void srm_console_write(struct con
 
 static kdev_t srm_console_device(struct console *c)
 {
-  /* Huh? */
-        return MKDEV(TTY_MAJOR, 64 + c->index);
+	/* Huh? */
+        return mk_kdev(TTY_MAJOR, 64 + c->index);
 }
 
 static int __init srm_console_setup(struct console *co, char *options)
diff -ruNp linux/arch/alpha/kernel/smp.c 2.5.3/arch/alpha/kernel/smp.c
--- linux/arch/alpha/kernel/smp.c	Tue Jan 15 10:56:35 2002
+++ 2.5.3/arch/alpha/kernel/smp.c	Thu Feb  7 14:51:03 2002
@@ -45,7 +45,7 @@
 #include "irq_impl.h"
 
 
-#define DEBUG_SMP 0
+#define DEBUG_SMP 1
 #if DEBUG_SMP
 #define DBGS(args)	printk args
 #else
@@ -62,6 +62,7 @@ static struct {
 
 enum ipi_message_type {
 	IPI_RESCHEDULE,
+	IPI_MIGRATION,
 	IPI_CALL_FUNC,
 	IPI_CPU_STOP,
 };
@@ -69,7 +70,7 @@ enum ipi_message_type {
 spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Set to a secondary's cpuid when it comes online.  */
-static unsigned long smp_secondary_alive;
+static int smp_secondary_alive __initdata = 0;
 
 /* Which cpus ids came online.  */
 unsigned long cpu_present_mask;
@@ -82,6 +83,7 @@ int smp_num_probed;		/* Internal process
 int smp_num_cpus = 1;		/* Number that came online.  */
 int smp_threads_ready;		/* True once the per process idle is forked. */
 cycles_t cacheflush_time;
+unsigned long cache_decay_ticks;
 
 int __cpu_number_map[NR_CPUS];
 int __cpu_logical_map[NR_CPUS];
@@ -132,7 +134,7 @@ smp_setup_percpu_timer(int cpuid)
 	cpu_data[cpuid].prof_multiplier = 1;
 }
 
-static void __init
+static inline void __init
 wait_boot_cpu_to_stop(int cpuid)
 {
 	long stop = jiffies + 10*HZ;
@@ -156,13 +158,6 @@ smp_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
-	if (current != init_tasks[cpu_number_map(cpuid)]) {
-		printk("BUG: smp_calling: cpu %d current %p init_tasks[cpu_number_map(cpuid)] %p\n",
-		       cpuid, current, init_tasks[cpu_number_map(cpuid)]);
-	}
-
-	DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state));
-
 	/* Turn on machine checks.  */
 	wrmces(7);
 
@@ -178,19 +173,15 @@ smp_callin(void)
 	/* Must have completely accurate bogos.  */
 	__sti();
 
-	/*
-	 * Wait boot CPU to stop with irq enabled before
-	 * running calibrate_delay().
-	 */
+	/* Wait boot CPU to stop with irq enabled before running
+	   calibrate_delay.  */
 	wait_boot_cpu_to_stop(cpuid);
 	mb();
 	calibrate_delay();
 
 	smp_store_cpu_info(cpuid);
-	/*
-	 * Allow master to continue only after we written
-	 * the loops_per_jiffy.
-	 */
+
+	/* Allow master to continue only after we written loops_per_jiffy.  */
 	wmb();
 	smp_secondary_alive = 1;
 
@@ -201,12 +192,6 @@ smp_callin(void)
 	DBGS(("smp_callin: commencing CPU %d current %p\n",
 	      cpuid, current));
 
-	/* Setup the scheduler for this processor.  */
-	init_idle();
-
-	/* ??? This should be in init_idle.  */
-	atomic_inc(&init_mm.mm_count);
-	current->active_mm = &init_mm;
 	/* Do nothing.  */
 	cpu_idle();
 }
@@ -222,8 +207,9 @@ static void __init
 smp_tune_scheduling (int cpuid)
 {
 	struct percpu_struct *cpu;
-	unsigned long on_chip_cache;
-	unsigned long freq;
+	unsigned long on_chip_cache;	/* kB */
+	unsigned long freq;		/* Hz */
+	unsigned long bandwidth = 350;	/* MB/s */
 
 	cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset
 				      + cpuid * hwrpb->processor_size);
@@ -244,43 +230,54 @@ smp_tune_scheduling (int cpuid)
 
 	case EV6_CPU:
 	case EV67_CPU:
-		on_chip_cache = 64 + 64;
-		break;
-
 	default:
-		on_chip_cache = 8 + 8;
+		on_chip_cache = 64 + 64;
 		break;
 	}
 
 	freq = hwrpb->cycle_freq ? : est_cycle_freq;
 
-#if 0
-	/* Magic estimation stolen from x86 port.  */
-	cacheflush_time = freq / 1024L * on_chip_cache / 5000L;
+	cacheflush_time = (freq / 1000000) * (on_chip_cache << 10) / bandwidth;
+	cache_decay_ticks = cacheflush_time / (freq / 1000) * HZ / 1000;
 
-        printk("Using heuristic of %d cycles.\n",
-               cacheflush_time);
-#else
-	/* Magic value to force potential preemption of other CPUs.  */
-	cacheflush_time = INT_MAX;
+        printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
+	       cacheflush_time/(freq/1000000),
+	       (cacheflush_time*100/(freq/1000000)) % 100);
+        printk("task migration cache decay timeout: %ld msecs.\n",
+	       (cache_decay_ticks + 1) * 1000 / HZ);
+}
 
-        printk("Using heuristic of %d cycles.\n",
-               cacheflush_time);
-#endif
+/* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
+static int __init
+wait_for_txrdy (unsigned long cpumask)
+{
+	unsigned long timeout;
+
+	if (!(hwrpb->txrdy & cpumask))
+		return 0;
+
+	timeout = jiffies + 10*HZ;
+	while (time_before(jiffies, timeout)) {
+		if (!(hwrpb->txrdy & cpumask))
+			return 0;
+		udelay(10);
+		barrier();
+	}
+
+	return -1;
 }
 
 /*
  * Send a message to a secondary's console.  "START" is one such
  * interesting message.  ;-)
  */
-static void
+static void __init
 send_secondary_console_msg(char *str, int cpuid)
 {
 	struct percpu_struct *cpu;
 	register char *cp1, *cp2;
 	unsigned long cpumask;
 	size_t len;
-	long timeout;
 
 	cpu = (struct percpu_struct *)
 		((char*)hwrpb
@@ -288,9 +285,8 @@ send_secondary_console_msg(char *str, in
 		 + cpuid * hwrpb->processor_size);
 
 	cpumask = (1UL << cpuid);
-	if (hwrpb->txrdy & cpumask)
-		goto delay1;
-	ready1:
+	if (wait_for_txrdy(cpumask))
+		goto timeout;
 
 	cp2 = str;
 	len = strlen(cp2);
@@ -302,34 +298,12 @@ send_secondary_console_msg(char *str, in
 	wmb();
 	set_bit(cpuid, &hwrpb->rxrdy);
 
-	if (hwrpb->txrdy & cpumask)
-		goto delay2;
-	ready2:
+	if (wait_for_txrdy(cpumask))
+		goto timeout;
 	return;
 
-delay1:
-	/* Wait 10 seconds.  Note that jiffies aren't ticking yet.  */
-	for (timeout = 1000000; timeout > 0; --timeout) {
-		if (!(hwrpb->txrdy & cpumask))
-			goto ready1;
-		udelay(10);
-		barrier();
-	}
-	goto timeout;
-
-delay2:
-	/* Wait 10 seconds.  */
-	for (timeout = 1000000; timeout > 0; --timeout) {
-		if (!(hwrpb->txrdy & cpumask))
-			goto ready2;
-		udelay(10);
-		barrier();
-	}
-	goto timeout;
-
-timeout:
+ timeout:
 	printk("Processor %x not ready\n", cpuid);
-	return;
 }
 
 /*
@@ -439,9 +413,9 @@ secondary_cpu_start(int cpuid, struct ta
 
 	send_secondary_console_msg("START\r\n", cpuid);
 
-	/* Wait 10 seconds for an ACK from the console.  Note that jiffies 
-	   aren't ticking yet.  */
-	for (timeout = 1000000; timeout > 0; timeout--) {
+	/* Wait 10 seconds for an ACK from the console.  */
+	timeout = jiffies + 10*HZ;
+	while (time_before(jiffies, timeout)) {
 		if (cpu->flags & 1)
 			goto started;
 		udelay(10);
@@ -455,13 +429,12 @@ started:
 	return 0;
 }
 
-static int __init fork_by_hand(void)
+static inline int __init
+fork_by_hand(void)
 {
 	struct pt_regs regs;
-	/*
-	 * don't care about the regs settings since
-	 * we'll never reschedule the forked task.
-	 */
+	/* Don't care about the regs settings since we'll never
+	   reschedule the forked task.  */
 	return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
 }
 
@@ -477,66 +450,53 @@ smp_boot_one_cpu(int cpuid, int cpunum)
 	/* Cook up an idler for this guy.  Note that the address we give
 	   to kernel_thread is irrelevant -- it's going to start where
 	   HWRPB.CPU_restart says to start.  But this gets all the other
-	   task-y sort of data structures set up like we wish.  */
-	/*
-	 * We can't use kernel_thread since we must avoid to
-	 * reschedule the child.
-	 */
+	   task-y sort of data structures set up like we wish.  We can't
+	   use kernel_thread since we must avoid rescheduling the child.  */
 	if (fork_by_hand() < 0)
 		panic("failed fork for CPU %d", cpuid);
 
 	idle = init_task.prev_task;
 	if (!idle)
 		panic("No idle process for CPU %d", cpuid);
-	if (idle == &init_task)
-		panic("idle process is init_task for CPU %d", cpuid);
+	init_idle(idle, cpuid);
 
-	idle->processor = cpuid;
-	idle->cpus_runnable = 1 << cpuid; /* we schedule the first task manually */
 	__cpu_logical_map[cpunum] = cpuid;
 	__cpu_number_map[cpuid] = cpunum;
  
-	del_from_runqueue(idle);
 	unhash_process(idle);
-	init_tasks[cpunum] = idle;
 
 	DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
 	      cpuid, idle->state, idle->flags));
 
-	/* The secondary will change this once it is happy.  Note that
-	   secondary_cpu_start contains the necessary memory barrier.  */
+	/* Signal the secondary CPU to wait a moment.  */
 	smp_secondary_alive = -1;
 
 	/* Whirrr, whirrr, whirrrrrrrrr... */
 	if (secondary_cpu_start(cpuid, idle))
 		return -1;
 
+	/* Notify the secondary CPU it can run calibrate_delay.  */
 	mb();
-	/* Notify the secondary CPU it can run calibrate_delay() */
 	smp_secondary_alive = 0;
 
-	/* We've been acked by the console; wait one second for the task
-	   to start up for real.  Note that jiffies aren't ticking yet.  */
-	for (timeout = 0; timeout < 1000000; timeout++) {
-		if (smp_secondary_alive == 1)
-			goto alive;
+	/* We've been acked by the console; wait one second for
+	   the task to start up for real.  */
+	timeout = jiffies + 1*HZ;
+	while (time_before(jiffies, timeout)) {
+		if (smp_secondary_alive == 1) {
+			/* Another "Red Snapper". */
+			return 0;
+		}
 		udelay(10);
 		barrier();
 	}
 
-	/* we must invalidate our stuff as we failed to boot the CPU */
+	/* We must invalidate our stuff as we failed to boot the CPU.  */
 	__cpu_logical_map[cpunum] = -1;
 	__cpu_number_map[cpuid] = -1;
 
-	/* the idle task is local to us so free it as we don't use it */
-	free_task_struct(idle);
-
 	printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
 	return -1;
-
-alive:
-	/* Another "Red Snapper". */
-	return 0;
 }
 
 /*
@@ -605,21 +565,16 @@ smp_boot_cpus(void)
 
 	__cpu_number_map[boot_cpuid] = 0;
 	__cpu_logical_map[0] = boot_cpuid;
-	current->processor = boot_cpuid;
+	current->cpu = boot_cpuid;
 
 	smp_store_cpu_info(boot_cpuid);
 	smp_tune_scheduling(boot_cpuid);
 	smp_setup_percpu_timer(boot_cpuid);
 
-	init_idle();
-
-	/* ??? This should be in init_idle.  */
-	atomic_inc(&init_mm.mm_count);
-	current->active_mm = &init_mm;
-
 	/* Nothing to do on a UP box, or when told not to.  */
 	if (smp_num_probed == 1 || max_cpus == 0) {
 		printk(KERN_INFO "SMP mode deactivated.\n");
+		cpu_present_mask = 1UL << boot_cpuid;
 		return;
 	}
 
@@ -707,26 +662,38 @@ setup_profiling_timer(unsigned int multi
 static void
 send_ipi_message(unsigned long to_whom, enum ipi_message_type operation)
 {
-	long i, j;
-
-	/* Reduce the number of memory barriers by doing two loops,
-	   one to set the bits, one to invoke the interrupts.  */
+	unsigned long i, set, n;
 
-	mb();	/* Order out-of-band data and bit setting. */
-
-	for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) {
-		if (to_whom & j)
-			set_bit(operation, &ipi_data[i].bits);
-	}
+	/* Special case sending to one cpu.  */
 
-	mb();	/* Order bit setting and interrupt. */
+	set = to_whom & -to_whom;
+	if (to_whom == set) {
+		n = __ffs(set);
+		mb();
+		set_bit(operation, &ipi_data[n].bits);
+		mb();
+		wripir(n);
+	} else {
+		mb();
+		for (i = to_whom; i ; i &= ~set) {
+			set = i & -i;
+			n = __ffs(set);
+			set_bit(operation, &ipi_data[n].bits);
+		}
 
-	for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) {
-		if (to_whom & j)
-			wripir(i);
+		mb();
+		for (i = to_whom; i ; i &= ~set) {
+			set = i & -i;
+			n = __ffs(set);
+			wripir(n);
+		}
 	}
 }
 
+/* Data for IPI_MIGRATION.  */
+static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
+static task_t *migration_task;
+
 /* Structure and data for smp_call_function.  This is designed to 
    minimize static memory requirements.  Plus it looks cleaner.  */
 
@@ -792,13 +759,23 @@ handle_ipi(struct pt_regs *regs)
 
 		which = ops & -ops;
 		ops &= ~which;
-		which = ffz(~which);
+		which = __ffs(which);
 
-		if (which == IPI_RESCHEDULE) {
+		switch (which) {
+		case IPI_RESCHEDULE:
 			/* Reschedule callback.  Everything to be done
 			   is done by the interrupt return path.  */
-		}
-		else if (which == IPI_CALL_FUNC) {
+			break;
+		case IPI_MIGRATION:
+		    {
+			task_t *t = migration_task;
+			mb();
+			spin_unlock(&migration_lock);
+			sched_task_migrated(t);
+			break;
+		    }
+		case IPI_CALL_FUNC:
+		    {
 			struct smp_call_struct *data;
 			void (*func)(void *info);
 			void *info;
@@ -821,13 +798,16 @@ handle_ipi(struct pt_regs *regs)
 			/* Notify the sending CPU that the task is done.  */
 			mb();
 			if (wait) atomic_dec (&data->unfinished_count);
-		}
-		else if (which == IPI_CPU_STOP) {
+			break;
+		    }
+		case IPI_CPU_STOP:
 			halt();
-		}
-		else {
+			break;
+
+		default:
 			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
 			       this_cpu, which);
+			break;
 		}
 	  } while (ops);
 
@@ -849,6 +829,20 @@ smp_send_reschedule(int cpu)
 		       "smp_send_reschedule: Sending IPI to self.\n");
 #endif
 	send_ipi_message(1UL << cpu, IPI_RESCHEDULE);
+}
+
+void
+smp_migrate_task(int cpu, task_t *t)
+{
+#if DEBUG_IPI_MSG
+	if (cpu == hard_smp_processor_id())
+		printk(KERN_WARNING
+		       "smp_migrate_task: Sending IPI to self.\n");
+#endif
+	/* The target CPU will unlock the migration spinlock.  */
+	spin_lock(&migration_lock);
+	migration_task = t;
+	send_ipi_message(1UL << cpu, IPI_MIGRATION);
 }
 
 void
diff -ruNp linux/arch/alpha/mm/fault.c 2.5.3/arch/alpha/mm/fault.c
--- linux/arch/alpha/mm/fault.c	Mon Sep 17 16:15:02 2001
+++ 2.5.3/arch/alpha/mm/fault.c	Sat Feb  2 15:38:22 2002
@@ -196,8 +196,7 @@ no_context:
  */
 out_of_memory:
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
diff -ruNp linux/arch/alpha/vmlinux.lds.in 2.5.3/arch/alpha/vmlinux.lds.in
--- linux/arch/alpha/vmlinux.lds.in	Wed Jan 23 10:54:42 2002
+++ 2.5.3/arch/alpha/vmlinux.lds.in	Sat Feb  2 16:18:49 2002
@@ -32,6 +32,8 @@ SECTIONS
   . = ALIGN(8192);
   __init_begin = .;
   .text.init : { *(.text.init) }
+  /* Don't discard .text.exit yet -- too many problems remaining.  */
+  .text.exit : { *(.text.exit) }
   .data.init : { *(.data.init) }
 
   . = ALIGN(16);
@@ -100,5 +102,5 @@ SECTIONS
   .debug_typenames 0 : { *(.debug_typenames) }
   .debug_varnames  0 : { *(.debug_varnames) }
 
-  /DISCARD/ : { *(.text.exit) *(.data.exit) *(.exitcall.exit) }
+  /DISCARD/ : { *(.data.exit) *(.exitcall.exit) }
 }
diff -ruNp linux/drivers/base/core.c 2.5.3/drivers/base/core.c
--- linux/drivers/base/core.c	Mon Jan 28 16:57:27 2002
+++ 2.5.3/drivers/base/core.c	Sat Feb  2 14:31:08 2002
@@ -7,7 +7,8 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/init.h>
 
 #undef DEBUG
 
diff -ruNp linux/drivers/base/fs.c 2.5.3/drivers/base/fs.c
--- linux/drivers/base/fs.c	Thu Jan 24 14:07:46 2002
+++ 2.5.3/drivers/base/fs.c	Sat Feb  2 14:45:19 2002
@@ -8,7 +8,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 extern struct driver_file_entry * device_default_files[];
 
diff -ruNp linux/drivers/block/ll_rw_blk.c 2.5.3/drivers/block/ll_rw_blk.c
--- linux/drivers/block/ll_rw_blk.c	Sat Jan 19 16:49:38 2002
+++ 2.5.3/drivers/block/ll_rw_blk.c	Thu Feb  7 14:41:15 2002
@@ -182,12 +182,14 @@ void blk_queue_bounce_limit(request_queu
 	static request_queue_t *last_q;
 
 	/*
-	 * set appropriate bounce gfp mask -- unfortunately we don't have a
+	 * Set appropriate bounce gfp mask -- unfortunately we don't have a
 	 * full 4GB zone, so we have to resort to low memory for any bounces.
 	 * ISA has its own < 16MB zone.
 	 */
 	if (bounce_pfn < blk_max_low_pfn) {
-		BUG_ON(dma_addr < BLK_BOUNCE_ISA);
+		/* Note that some systems have an ISA bridge that frobs
+		   addresses, so there may be no 16MB limit.  */
+		BUG_ON(dma_addr < BLK_BOUNCE_ISA && BLK_BOUNCE_ISA < ~0UL);
 		init_emergency_isa_pool();
 		q->bounce_gfp = GFP_NOIO | GFP_DMA;
 	} else
diff -ruNp linux/include/asm-alpha/asm_offsets.h 2.5.3/include/asm-alpha/asm_offsets.h
--- linux/include/asm-alpha/asm_offsets.h	Mon Oct 12 11:40:12 1998
+++ 2.5.3/include/asm-alpha/asm_offsets.h	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-#ifndef __ASM_OFFSETS_H__
-#define __ASM_OFFSETS_H__
-#define TASK_STATE 0
-#define TASK_FLAGS 8
-#define TASK_SIGPENDING 16
-#define TASK_ADDR_LIMIT 24
-#define TASK_EXEC_DOMAIN 32
-#define TASK_NEED_RESCHED 40
-#define TASK_SIZE 1096
-#define STACK_SIZE 16384
-#define HAE_CACHE 0
-#define HAE_REG 8
-#endif /* __ASM_OFFSETS_H__ */
diff -ruNp linux/include/asm-alpha/bitops.h 2.5.3/include/asm-alpha/bitops.h
--- linux/include/asm-alpha/bitops.h	Fri Oct 12 15:35:54 2001
+++ 2.5.3/include/asm-alpha/bitops.h	Thu Feb  7 14:52:42 2002
@@ -74,11 +74,11 @@ clear_bit(unsigned long nr, volatile voi
  * WARNING: non atomic version.
  */
 static __inline__ void
-__change_bit(unsigned long nr, volatile void * addr)
+__clear_bit(unsigned long nr, volatile void * addr)
 {
 	int *m = ((int *) addr) + (nr >> 5);
 
-	*m ^= 1 << (nr & 31);
+	*m &= ~(1 << (nr & 31));
 }
 
 static inline void
@@ -99,6 +99,17 @@ change_bit(unsigned long nr, volatile vo
 	:"Ir" (1UL << (nr & 31)), "m" (*m));
 }
 
+/*
+ * WARNING: non atomic version.
+ */
+static __inline__ void
+__change_bit(unsigned long nr, volatile void * addr)
+{
+	int *m = ((int *) addr) + (nr >> 5);
+
+	*m ^= 1 << (nr & 31);
+}
+
 static inline int
 test_and_set_bit(unsigned long nr, volatile void *addr)
 {
@@ -181,20 +192,6 @@ __test_and_clear_bit(unsigned long nr, v
 	return (old & mask) != 0;
 }
 
-/*
- * WARNING: non atomic version.
- */
-static __inline__ int
-__test_and_change_bit(unsigned long nr, volatile void * addr)
-{
-	unsigned long mask = 1 << (nr & 0x1f);
-	int *m = ((int *) addr) + (nr >> 5);
-	int old = *m;
-
-	*m = old ^ mask;
-	return (old & mask) != 0;
-}
-
 static inline int
 test_and_change_bit(unsigned long nr, volatile void * addr)
 {
@@ -220,6 +217,20 @@ test_and_change_bit(unsigned long nr, vo
 	return oldbit != 0;
 }
 
+/*
+ * WARNING: non atomic version.
+ */
+static __inline__ int
+__test_and_change_bit(unsigned long nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	int *m = ((int *) addr) + (nr >> 5);
+	int old = *m;
+
+	*m = old ^ mask;
+	return (old & mask) != 0;
+}
+
 static inline int
 test_bit(int nr, volatile void * addr)
 {
@@ -264,17 +275,39 @@ static inline unsigned long ffz(unsigned
 #endif
 }
 
+/*
+ * __ffs = Find First set bit in word.  Undefined if no set bit exists.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+#if defined(__alpha_cix__) && defined(__alpha_fix__)
+	/* Whee.  EV67 can calculate it directly.  */
+	unsigned long result;
+	__asm__("cttz %1,%0" : "=r"(result) : "r"(word));
+	return result;
+#else
+	unsigned long bits, qofs, bofs;
+
+	__asm__("cmpbge $31,%1,%0" : "=r"(bits) : "r"(word));
+	qofs = ffz_b(bits);
+	__asm__("extbl %1,%2,%0" : "=r"(bits) : "r"(word), "r"(qofs));
+	bofs = ffz_b(~bits);
+
+	return qofs*8 + bofs;
+#endif
+}
+
 #ifdef __KERNEL__
 
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * differs in spirit from the above ffo (man ffs).
  */
 
 static inline int ffs(int word)
 {
-	int result = ffz(~word);
+	int result = __ffs(word);
 	return word ? result+1 : 0;
 }
 
@@ -365,10 +398,53 @@ found_middle:
 }
 
 /*
- * The optimizer actually does good code for this case..
+ * Find next one bit in a bitmap reasonably efficiently.
+ */
+static inline unsigned long
+find_next_bit(void * addr, unsigned long size, unsigned long offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+	unsigned long result = offset & ~63UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 63UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp &= ~0UL << offset;
+		if (size < 64)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= 64;
+		result += 64;
+	}
+	while (size & ~63UL) {
+		if ((tmp = *(p++)))
+			goto found_middle;
+		result += 64;
+		size -= 64;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+found_first:
+	tmp &= ~0UL >> (64 - size);
+	if (!tmp)
+		return result + size;
+found_middle:
+	return result + __ffs(tmp);
+}
+
+/*
+ * The optimizer actually does good code for this case.
  */
 #define find_first_zero_bit(addr, size) \
 	find_next_zero_bit((addr), (size), 0)
+#define find_first_bit(addr, size) \
+	find_next_bit((addr), (size), 0)
 
 #ifdef __KERNEL__
 
diff -ruNp linux/include/asm-alpha/io.h 2.5.3/include/asm-alpha/io.h
--- linux/include/asm-alpha/io.h	Tue Nov 27 09:23:27 2001
+++ 2.5.3/include/asm-alpha/io.h	Thu Feb  7 14:52:42 2002
@@ -18,6 +18,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
+#include <asm/pgtable.h>
 #include <asm/machvec.h>
 
 /*
@@ -60,7 +61,10 @@ static inline void * phys_to_virt(unsign
 	return (void *) (address + IDENT_ADDR);
 }
 
-#define page_to_phys(page)	(((page) - (page)->zone->zone_mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)	PAGE_TO_PA(page)
+
+/* This depends on working iommu.  */
+#define BIO_VMERGE_BOUNDARY	(alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
 
 /*
  * Change addresses as seen by the kernel (virtual) to addresses as
diff -ruNp linux/include/asm-alpha/mmu_context.h 2.5.3/include/asm-alpha/mmu_context.h
--- linux/include/asm-alpha/mmu_context.h	Fri Dec 29 14:07:23 2000
+++ 2.5.3/include/asm-alpha/mmu_context.h	Thu Feb  7 14:52:48 2002
@@ -21,6 +21,32 @@
 #include <asm/io.h>
 #endif
 
+/* ??? This does not belong here.  */
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 168
+ * bits is set.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO > 192
+# error update this function.
+#endif
+
+static inline int
+sched_find_first_bit(unsigned long *b)
+{
+	unsigned long b0 = b[0], b1 = b[1], b2 = b[2];
+	unsigned long offset = 128;
+
+	if (unlikely(b0 | b1)) {
+		b2 = (b0 ? b0 : b1);
+		offset = (b0 ? 0 : 64);
+	}
+
+	return __ffs(b2) + offset;
+}
+
+
 extern inline unsigned long
 __reload_thread(struct thread_struct *pcb)
 {
diff -ruNp linux/include/asm-alpha/smp.h 2.5.3/include/asm-alpha/smp.h
--- linux/include/asm-alpha/smp.h	Thu Sep 13 15:21:32 2001
+++ 2.5.3/include/asm-alpha/smp.h	Thu Feb  7 14:52:42 2002
@@ -55,7 +55,7 @@ extern int __cpu_logical_map[NR_CPUS];
 #define cpu_logical_map(cpu)  __cpu_logical_map[cpu]
 
 #define hard_smp_processor_id()	__hard_smp_processor_id()
-#define smp_processor_id()	(current->processor)
+#define smp_processor_id()	(current->cpu)
 
 extern unsigned long cpu_present_mask;
 #define cpu_online_map cpu_present_mask
diff -ruNp linux/include/asm-alpha/unistd.h 2.5.3/include/asm-alpha/unistd.h
--- linux/include/asm-alpha/unistd.h	Fri Nov  9 13:45:35 2001
+++ 2.5.3/include/asm-alpha/unistd.h	Thu Feb  7 14:52:42 2002
@@ -575,6 +575,9 @@ static inline long sync(void)
 	return sys_sync();
 }
 
+struct rusage;
+extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
+				 int options, struct rusage * ru);
 static inline pid_t waitpid(int pid, int * wait_stat, int flags)
 {
 	return sys_wait4(pid, wait_stat, flags, NULL);
diff -ruNp linux/include/linux/dcache.h 2.5.3/include/linux/dcache.h
--- linux/include/linux/dcache.h	Tue Jan 29 21:41:09 2002
+++ 2.5.3/include/linux/dcache.h	Thu Feb  7 13:16:40 2002
@@ -5,6 +5,8 @@
 
 #include <asm/atomic.h>
 #include <linux/mount.h>
+#include <asm/page.h>           /* BUG */
+
 
 /*
  * linux/include/linux/dcache.h
diff -ruNp linux/include/linux/nfs_fs.h 2.5.3/include/linux/nfs_fs.h
--- linux/include/linux/nfs_fs.h	Tue Jan 29 21:42:01 2002
+++ 2.5.3/include/linux/nfs_fs.h	Thu Feb  7 14:52:44 2002
@@ -22,6 +22,8 @@
 #include <linux/nfs3.h>
 #include <linux/nfs_xdr.h>
 
+#include <asm/page.h>		/* BUG */
+
 /*
  * Enable debugging support for nfs client.
  * Requires RPC_DEBUG.

       reply	other threads:[~2002-02-08  1:06 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20020207211329.A861@jurassic.park.msu.ru>
2002-02-08  0:59 ` Richard Henderson [this message]
2002-02-08  1:20   ` Alpha update for 2.5.3 Jeff Garzik
2002-02-08  1:56     ` Skip Ford
2002-02-08  3:53       ` Andre Hedrick
2002-02-08  4:06         ` Skip Ford
2002-02-08  9:33           ` Jens Axboe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020207165949.A3759@are.twiddle.net \
    --to=rth@twiddle.net \
    --cc=Jay.Estabrook@compaq.com \
    --cc=andrea@suse.de \
    --cc=frival@zk3.dec.com \
    --cc=ink@jurassic.park.msu.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.