## Automatically generated incremental diff
## From:   linux-2.2.19-pre5
## To:     linux-2.2.19-pre6
## Robot:  $Id: make-incremental-diff,v 1.6 2001/12/04 04:41:15 hpa Exp $

diff -urN linux-2.2.19-pre5/Makefile linux/Makefile
--- linux-2.2.19-pre5/Makefile	Mon Dec  3 20:56:35 2001
+++ linux/Makefile	Mon Dec  3 20:57:03 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 19
-EXTRAVERSION = pre5
+EXTRAVERSION = pre6
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.19-pre5/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- linux-2.2.19-pre5/arch/alpha/kernel/alpha_ksyms.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Mon Dec  3 20:57:03 2001
@@ -169,6 +169,7 @@
 EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_bh_count);
 EXPORT_SYMBOL(synchronize_bh);
+EXPORT_SYMBOL(alpha_bh_lock);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
diff -urN linux-2.2.19-pre5/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- linux-2.2.19-pre5/arch/alpha/kernel/irq.c	Wed Jun  7 14:26:42 2000
+++ linux/arch/alpha/kernel/irq.c	Mon Dec  3 20:57:03 2001
@@ -385,6 +385,7 @@
 /* This protects BH software state (masks, things like that). */
 atomic_t global_bh_lock = ATOMIC_INIT(0);
 atomic_t global_bh_count = ATOMIC_INIT(0);
+spinlock_t alpha_bh_lock = SPIN_LOCK_UNLOCKED;
 
 static void *previous_irqholder = NULL;
 
@@ -650,6 +651,7 @@
 void
 synchronize_bh(void)
 {
+	mb();
 	if (atomic_read(&global_bh_count) && !in_interrupt())
 			wait_on_bh();
 }
diff -urN linux-2.2.19-pre5/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- linux-2.2.19-pre5/arch/alpha/kernel/process.c	Wed May  3 17:16:30 2000
+++ linux/arch/alpha/kernel/process.c	Mon Dec  3 20:57:03 2001
@@ -249,8 +249,11 @@
 	alpha_mv.kill_arch(LINUX_REBOOT_CMD_POWER_OFF, NULL);
 }
 
-void show_regs(struct pt_regs * regs)
+void __show_regs(struct pt_regs * regs)
 {
+	extern void dik_show_trace(unsigned long *);
+
+	printk("\nCPU: %d", smp_processor_id());
 	printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc);
 	printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
 	printk(" r0: %016lx  r1: %016lx  r2: %016lx  r3: %016lx\n",
@@ -265,6 +268,15 @@
 	       regs->r23, regs->r24, regs->r25, regs->r26);
 	printk("r27: %016lx r28: %016lx r29: %016lx hae: %016lx\n",
 	       regs->r27, regs->r28, regs->gp, regs->hae);
+	dik_show_trace(regs+1);
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	__show_regs(regs);
+#ifdef CONFIG_SMP
+	smp_show_regs();
+#endif
 }
 
 /*
diff -urN linux-2.2.19-pre5/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- linux-2.2.19-pre5/arch/alpha/kernel/smp.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/alpha/kernel/smp.c	Mon Dec  3 20:57:03 2001
@@ -95,8 +95,7 @@
 smp_store_cpu_info(int cpuid)
 {
 	cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
-	cpu_data[cpuid].last_asn
-	  = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION;
+	cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
 
         cpu_data[cpuid].irq_count = 0;
         cpu_data[cpuid].bh_count = 0;
@@ -739,7 +738,14 @@
 
 			/* At this point the structure may be gone unless
 			   wait is true.  */
-			(*func)(info);
+			{
+			static void ipi_show_regs(void *);
+
+			if (func != ipi_show_regs)
+				(*func)(info);
+			else
+				(*func)((void *) regs);
+			}
 
 			/* Notify the sending CPU that the task is done.  */
 			mb();
@@ -856,6 +862,21 @@
 }
 
 static void
+ipi_show_regs(void * param)
+{
+	struct pt_regs *regs = (struct pt_regs *) param;
+
+	__show_regs(regs);
+}
+
+void
+smp_show_regs(void)
+{
+	if (smp_call_function(ipi_show_regs, NULL, 1, 1))
+		printk(KERN_CRIT "smp_show_regs: timed out\n");
+}
+
+static void
 ipi_flush_tlb_all(void *ignored)
 {
 	tbia();
@@ -879,6 +900,8 @@
 	struct mm_struct *mm = (struct mm_struct *) x;
 	if (mm == current->mm)
 		flush_tlb_current(mm);
+	else
+		flush_tlb_other(mm);
 }
 
 void
@@ -886,10 +909,17 @@
 {
 	if (mm == current->mm) {
 		flush_tlb_current(mm);
-		if (atomic_read(&mm->count) == 1)
+		if (atomic_read(&mm->count) == 1) {
+			int i, cpu, this_cpu = smp_processor_id();
+			for (i = 0; i < smp_num_cpus; i++) {
+				cpu = cpu_logical_map(i);
+				if (cpu == this_cpu)
+					continue;
+				mm->context[cpu] = 0;
+			}
 			return;
-	} else
-		flush_tlb_other(mm);
+		}
+	}
 
 	if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_mm: timed out\n");
@@ -906,8 +936,12 @@
 ipi_flush_tlb_page(void *x)
 {
 	struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
-	if (data->mm == current->mm)
-		flush_tlb_current_page(data->mm, data->vma, data->addr);
+	struct mm_struct * mm = data->mm;
+
+	if (mm == current->mm)
+		flush_tlb_current_page(mm, data->vma, data->addr);
+	else
+		flush_tlb_other(mm);
 }
 
 void
@@ -918,10 +952,17 @@
 
 	if (mm == current->mm) {
 		flush_tlb_current_page(mm, vma, addr);
-		if (atomic_read(&current->mm->count) == 1)
+		if (atomic_read(&current->mm->count) == 1) {
+			int i, cpu, this_cpu = smp_processor_id();
+			for (i = 0; i < smp_num_cpus; i++) {
+				cpu = cpu_logical_map(i);
+				if (cpu == this_cpu)
+					continue;
+				mm->context[cpu] = 0;
+			}
 			return;
-	} else
-		flush_tlb_other(mm);
+		}
+	}
        
 	data.vma = vma;
 	data.mm = mm;
diff -urN linux-2.2.19-pre5/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- linux-2.2.19-pre5/arch/alpha/kernel/traps.c	Wed Jun  7 14:26:42 2000
+++ linux/arch/alpha/kernel/traps.c	Mon Dec  3 20:57:03 2001
@@ -269,7 +269,7 @@
 	}
 }
 
-static void
+void
 dik_show_trace(unsigned long *sp)
 {
 	int i = 1;
diff -urN linux-2.2.19-pre5/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- linux-2.2.19-pre5/arch/alpha/mm/fault.c	Mon Sep  4 10:39:16 2000
+++ linux/arch/alpha/mm/fault.c	Mon Dec  3 20:57:03 2001
@@ -41,7 +41,7 @@
 get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
 {
 	unsigned long new = __get_new_mmu_context();
-	mm->context = new;
+	mm->context[smp_processor_id()] = new;
 	p->tss.asn = new & HARDWARE_ASN_MASK;
 }
 
diff -urN linux-2.2.19-pre5/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux-2.2.19-pre5/arch/i386/kernel/traps.c	Mon Dec  3 20:56:35 2001
+++ linux/arch/i386/kernel/traps.c	Mon Dec  3 20:57:03 2001
@@ -155,7 +155,7 @@
 		printk("\nStack: ");
 		stack = (unsigned long *) esp;
 		for(i=0; i < kstack_depth_to_print; i++) {
-			if (((long) stack & 4095) == 0)
+			if (((long) stack & 8191) == 0)
 				break;
 			if (i && ((i % 8) == 0))
 				printk("\n       ");
@@ -170,7 +170,7 @@
 			module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
 			module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
 			module_end = module_start + MODULE_RANGE;
-			while (((long) stack & 4095) != 0) {
+			while (((long) stack & 8191) != 0) {
 				addr = *stack++;
 				/*
 				 * If the address is either in the text segment of the
diff -urN linux-2.2.19-pre5/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.2.19-pre5/drivers/sound/Config.in	Mon Dec  3 20:56:35 2001
+++ linux/drivers/sound/Config.in	Mon Dec  3 20:57:05 2001
@@ -312,7 +312,10 @@
   fi
   
   dep_tristate 'NM256AV/NM256ZX audio support' CONFIG_SOUND_NM256 $CONFIG_SOUND_OSS
-  dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
+  dep_tristate 'Yamaha PCI native mode support' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
+  if [ "$CONFIG_SOUND_YMFPCI" != "n" ]; then
+    bool '  Yamaha PCI legacy ports support' CONFIG_SOUND_YMFPCI_LEGACY
+  fi
 
   # Additional low level drivers.
   
diff -urN linux-2.2.19-pre5/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.2.19-pre5/drivers/sound/Makefile	Mon Dec  3 20:56:35 2001
+++ linux/drivers/sound/Makefile	Mon Dec  3 20:57:05 2001
@@ -98,7 +98,10 @@
 obj-$(CONFIG_SOUND_SONICVIBES)	+= sonicvibes.o
 obj-$(CONFIG_SOUND_TRIDENT)     += trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
-obj-$(CONFIG_SOUND_YMFPCI)	+= ymfpci.o ac97_codec.o uart401.o
+obj-$(CONFIG_SOUND_YMFPCI)	+= ymfpci.o ac97_codec.o
+ifeq ($(CONFIG_SOUND_YMFPCI_LEGACY),y)
+  obj-$(CONFIG_SOUND_YMFPCI)	+= opl3.o uart401.o
+endif
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
   obj-y				+= emu10k1/emu10k1.o
diff -urN linux-2.2.19-pre5/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- linux-2.2.19-pre5/drivers/sound/ymfpci.c	Mon Dec  3 20:56:35 2001
+++ linux/drivers/sound/ymfpci.c	Mon Dec  3 20:57:05 2001
@@ -34,8 +34,6 @@
  *      ? underused structure members
  */
 
-#define YMFPCI_HAVE_MIDI_SUPPORT
-
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -48,10 +46,9 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 # include "sound_config.h"
 #endif
-
 #include "ymfpci.h"
 
 #define snd_magic_cast(t, p, err)	((t *)(p))
@@ -65,7 +62,7 @@
     int pair, ymfpci_voice_t **rvoice);
 static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
 static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state);
-static int ymf_state_alloc(ymfpci_t *unit, int nvirt, int instance);
+static int ymf_state_alloc(ymfpci_t *unit, int nvirt);
 
 static ymfpci_t *ymf_devs = NULL;
 
@@ -606,11 +603,9 @@
 	char silence;
 
 	if ((ypcm = voice->ypcm) == NULL) {
-/* P3 */ printk("ymf_pcm_interrupt: voice %d: no ypcm\n", voice->number);
 		return;
 	}
 	if ((state = ypcm->state) == NULL) {
-/* P3 */ printk("ymf_pcm_interrupt: voice %d: no state\n", voice->number);
 		ypcm->running = 0;	// lock it
 		return;
 	}
@@ -632,7 +627,7 @@
 		if (pos < 0 || pos >= dmabuf->dmasize) {	/* ucode bug */
 			printk(KERN_ERR
 			    "ymfpci%d: %d: runaway: hwptr %d dmasize %d\n",
-			    codec->inst, voice->number,
+			    codec->dev_audio, voice->number,
 			    dmabuf->hwptr, dmabuf->dmasize);
 			pos = 0;
 		}
@@ -649,7 +644,7 @@
 
 		if (dmabuf->count == 0) {
 			printk("ymfpci%d: %d: strain: hwptr %d\n",
-			    codec->inst, voice->number, dmabuf->hwptr);
+			    codec->dev_audio, voice->number, dmabuf->hwptr);
 			ymf_playback_trigger(codec, ypcm, 0);
 		}
 
@@ -668,7 +663,7 @@
 				 */
 				printk("ymfpci%d: %d: lost: delta %d"
 				    " hwptr %d swptr %d distance %d count %d\n",
-				    codec->inst, voice->number, delta,
+				    codec->dev_audio, voice->number, delta,
 				    dmabuf->hwptr, swptr, distance, dmabuf->count);
 			} else {
 				/*
@@ -676,7 +671,7 @@
 				 */
 //				printk("ymfpci%d: %d: done: delta %d"
 //				    " hwptr %d swptr %d distance %d count %d\n",
-//				    codec->inst, voice->number, delta,
+//				    codec->dev_audio, voice->number, delta,
 //				    dmabuf->hwptr, swptr, distance, dmabuf->count);
 			}
 			played = dmabuf->count;
@@ -742,7 +737,6 @@
 {
 
 	if (ypcm->voices[0] == NULL) {
-/* P3 */ printk("ymfpci: trigger %d no voice\n", cmd);
 		return -EINVAL;
 	}
 	if (cmd != 0) {
@@ -832,8 +826,8 @@
 		end >>= 1;
 	if (w_16)
 		end >>= 1;
-/* P3 */ // printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n",
-//  voice->number, rate, format, delta, end);
+/* P3 */ /** printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n",
+  voice->number, rate, format, delta, end); **/
 	for (nbank = 0; nbank < 2; nbank++) {
 		bank = &voice->bank[nbank];
 		bank->format = format;
@@ -915,7 +909,7 @@
 	if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) {
 		/* Cannot be unless we leak voices in ymf_release! */
 		printk(KERN_ERR "ymfpci%d: cannot allocate voice!\n",
-		    codec->inst);
+		    codec->dev_audio);
 		return err;
 	}
 
@@ -1033,6 +1027,12 @@
 			if (voice->interrupt)
 				voice->interrupt(codec, voice);
 		}
+#if HAVE_RECORD
+		for (nvoice = 0; nvoice < 5; nvoice++) {
+			if (codec->capture_substream[nvoice])
+				snd_ymfpci_pcm_capture_interrupt(codec->capture_substream[nvoice]);
+		}
+#endif
 		spin_unlock(&codec->voice_lock);
 	}
 
@@ -1056,7 +1056,7 @@
 	}
 }
 
-static int ymf_state_alloc(ymfpci_t *unit, int nvirt, int instance)
+static int ymf_state_alloc(ymfpci_t *unit, int nvirt)
 {
 	ymfpci_pcm_t *ypcm;
 	struct ymf_state *state;
@@ -1542,12 +1542,13 @@
 		return put_user(SOUND_VERSION, (int *)arg);
 
 	case SNDCTL_DSP_RESET:
-		/* FIXME: spin_lock ? */
 		if (file->f_mode & FMODE_WRITE) {
 			ymf_wait_dac(state);
+			// spin_lock_irqsave(&state->unit->reg_lock, flags);
 			dmabuf->ready = 0;
 			dmabuf->swptr = dmabuf->hwptr = 0;
 			dmabuf->count = dmabuf->total_bytes = 0;
+			// spin_unlock_irqrestore(&state->unit->reg_lock, flags);
 		}
 #if HAVE_RECORD
 		if (file->f_mode & FMODE_READ) {
@@ -1576,9 +1577,7 @@
 
 	case SNDCTL_DSP_SPEED: /* set smaple rate */
 		get_user_ret(val, (int *)arg, -EFAULT);
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SPEED %d\n", val); */
 		if (val >= 8000 && val <= 48000) {
-			spin_lock_irqsave(&state->unit->reg_lock, flags);
 			if (file->f_mode & FMODE_WRITE) {
 				ymf_wait_dac(state);
 			}
@@ -1587,6 +1586,7 @@
 				stop_adc(state);
 			}
 #endif
+			spin_lock_irqsave(&state->unit->reg_lock, flags);
 			dmabuf->ready = 0;
 			state->format.rate = val;
 			ymf_pcm_update_shift(&state->format);
@@ -1602,7 +1602,6 @@
 	 */
 	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
 		get_user_ret(val, (int *)arg, -EFAULT);
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_STEREO %d\n", val); */
 		if (file->f_mode & FMODE_WRITE) {
 			ymf_wait_dac(state); 
 			spin_lock_irqsave(&state->unit->reg_lock, flags);
@@ -1624,7 +1623,6 @@
 		return 0;
 
 	case SNDCTL_DSP_GETBLKSIZE:
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETBLKSIZE\n"); */
 		if (file->f_mode & FMODE_WRITE) {
 			if ((val = prog_dmabuf(state, 0)))
 				return val;
@@ -1638,14 +1636,11 @@
 		return -EINVAL;
 
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETFMTS\n"); */
 		return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
 
 	case SNDCTL_DSP_SETFMT: /* Select sample format */
 		get_user_ret(val, (int *)arg, -EFAULT);
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SETFMT 0x%x\n", val); */
 		if (val == AFMT_S16_LE || val == AFMT_U8) {
-			spin_lock_irqsave(&state->unit->reg_lock, flags);
 			if (file->f_mode & FMODE_WRITE) {
 				ymf_wait_dac(state);
 			}
@@ -1654,6 +1649,7 @@
 				stop_adc(state);
 			}
 #endif
+			spin_lock_irqsave(&state->unit->reg_lock, flags);
 			dmabuf->ready = 0;
 			state->format.format = val;
 			ymf_pcm_update_shift(&state->format);
@@ -1663,15 +1659,15 @@
 
 	case SNDCTL_DSP_CHANNELS:
 		get_user_ret(val, (int *)arg, -EFAULT);
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_CHANNELS 0x%x\n", val); */
 		if (val != 0) {
-			spin_lock_irqsave(&state->unit->reg_lock, flags);
 			if (file->f_mode & FMODE_WRITE) {
 				ymf_wait_dac(state);
 				if (val == 1 || val == 2) {
+					spin_lock_irqsave(&state->unit->reg_lock, flags);
 					dmabuf->ready = 0;
 					state->format.voices = val;
 					ymf_pcm_update_shift(&state->format);
+					spin_unlock_irqrestore(&state->unit->reg_lock, flags);
 				}
 			}
 #if HAVE_RECORD
@@ -1680,7 +1676,6 @@
 				dmabuf->ready = 0;
 			}
 #endif
-			spin_unlock_irqrestore(&state->unit->reg_lock, flags);
 		}
 		return put_user(state->format.voices, (int *)arg);
 
@@ -1696,7 +1691,6 @@
 		 * The paragraph above is a clumsy way to say "flush ioctl".
 		 * This ioctl is used by mpg123.
 		 */
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_POST\n"); */
 		spin_lock_irqsave(&state->unit->reg_lock, flags);
 		if (dmabuf->count != 0 && !state->ypcm.running) {
 			ymf_start_dac(state);
@@ -1732,7 +1726,6 @@
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETOSPACE\n"); */
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
@@ -1763,12 +1756,10 @@
 #endif
 
 	case SNDCTL_DSP_NONBLOCK:
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_NONBLOCK\n"); */
 		file->f_flags |= O_NONBLOCK;
 		return 0;
 
 	case SNDCTL_DSP_GETCAPS:
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETCAPS\n"); */
 		/* return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
 			    (int *)arg); */
 		return put_user(0, (int *)arg);
@@ -1820,7 +1811,6 @@
 #endif
 
 	case SNDCTL_DSP_GETOPTR:
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETOPTR\n"); */
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
 		spin_lock_irqsave(&state->unit->reg_lock, flags);
@@ -1834,7 +1824,6 @@
 		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
 
 	case SNDCTL_DSP_SETDUPLEX:	/* XXX TODO */
-	/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SETDUPLEX\n"); */
 		return -EINVAL;
 
 #if 0 /* old */
@@ -1865,7 +1854,7 @@
 		return -ENOTTY;
 
 	default:
-	/* P3 */ printk("ymfpci: ioctl cmd 0x%x\n", cmd);
+	/* P3 */ /* printk("ymfpci: ioctl cmd 0x%x\n", cmd); */
 		/*
 		 * Some programs mix up audio devices and ioctls
 		 * or perhaps they expect "universal" ioctls,
@@ -1876,7 +1865,7 @@
 	return -ENOTTY;
 }
 
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 /* MIDI stuff */
 
 /* */
@@ -1939,10 +1928,10 @@
 		case PCI_DEVICE_ID_YAMAHA_754:
 			v = 0x8800;
 			pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
-			if ( mpuio >= 0 ) {
+			if ( oplio >= 0 ) {
 				pci_write_config_word(pcidev, PCIR_OPLADR, codec->iosynth);
 			}
-			if ( oplio >= 0 ) {
+			if ( mpuio >= 0 ) {
 				pci_write_config_word(pcidev, PCIR_MPUADR, codec->iomidi);
 			}
 		break;
@@ -1956,14 +1945,14 @@
 
 	return 0;
 }
-#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
 
 /* */
 
 static int ymf_open(struct inode *inode, struct file *file)
 {
 	ymfpci_t *unit;
-	int minor, instance;
+	int minor;
 	struct ymf_state *state;
 	int nvirt;
 	int err;
@@ -1980,25 +1969,21 @@
 	} else {
 		return -ENXIO;
 	}
-	instance = (minor >> 4) & 0x0F;
 	nvirt = 0;			/* Such is the partitioning of minor */
 
-	/* XXX Semaphore here! */
 	for (unit = ymf_devs; unit != NULL; unit = unit->next) {
-#if 0
-		if (unit->inst == instance) break;
-#else
-		if (!((unit->dev_audio ^ minor) & ~0x0f)) break;
-#endif
+		if (((unit->dev_audio ^ minor) & ~0x0f) == 0) break;
 	}
 	if (unit == NULL) return -ENODEV;
 
+	down(&unit->open_sem);
 	if (unit->states[nvirt] != NULL) {
-		/* P3 */ printk("ymfpci%d: busy\n", unit->inst);
+		up(&unit->open_sem);
 		return -EBUSY;
 	}
 
-	if ((err = ymf_state_alloc(unit, nvirt, instance)) != 0) {
+	if ((err = ymf_state_alloc(unit, nvirt)) != 0) {
+		up(&unit->open_sem);
 		return err;
 	}
 	state = unit->states[nvirt];
@@ -2006,11 +1991,12 @@
 	file->private_data = state;
 
 	/*
-	 * XXX This ymf_playback_prepare is totally unneeded here.
-	 * The question is if we want to allow write to fail if
-	 * prog_dmabuf fails... Say, no memory in DMA zone?
+	 * ymf_read and ymf_write that we borrowed from cs46xx
+	 * allocate buffers with prog_dmabuf(). We call prog_dmabuf
+	 * here so that in case of DMA memory exhaustion open
+	 * fails rather than write.
 	 */
-	if ((err = ymf_playback_prepare(unit, state)) != 0) {
+	if (!state->dmabuf.ready && (err = prog_dmabuf(state, 0))) {
 		/* XXX This recovery is ugly as hell. */
 
 		ymf_pcm_free_substream(&state->ypcm);
@@ -2018,6 +2004,7 @@
 		unit->states[state->virt] = NULL;
 		kfree(state);
 
+		up(&unit->open_sem);
 		return err;
 	}
 
@@ -2027,6 +2014,9 @@
 	    (YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN));
 #endif
 
+	up(&unit->open_sem);
+	/* XXX Ask Alan why MOD_INC_USE_COUNT is outside the semaphore. */
+
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -2040,14 +2030,14 @@
 	ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0);
 #endif
 
-	/* XXX Use the semaphore to unrace us with opens */
-
 	if (state != codec->states[state->virt]) {
 		printk(KERN_ERR "ymfpci%d.%d: state mismatch\n",
-		    state->unit->inst, state->virt);
+		    state->unit->dev_audio, state->virt);
 		return -EIO;
 	}
 
+	down(&codec->open_sem);
+
 	/*
 	 * XXX Solve the case of O_NONBLOCK close - don't deallocate here.
 	 * Deallocate when unloading the driver and we can wait.
@@ -2059,6 +2049,8 @@
 	codec->states[state->virt] = NULL;
 	kfree(state);
 
+	up(&codec->open_sem);
+
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -2151,8 +2143,7 @@
 	if (val)
 		ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000000);
 	while (timeout-- > 0) {
-		val = ymfpci_readl(codec, YDSXGR_CONFIG);
-		if ((val & 0x00000002) == 0)
+		if ((ymfpci_readl(codec, YDSXGR_STATUS) & 2) == 0)
 			break;
 	}
 }
@@ -2229,6 +2220,12 @@
 	ptr += 0x00ff;
 	(long)ptr &= ~0x00ff;
 
+	/*
+	 * Hardware requires only ptr[playback_ctrl_size] zeroed,
+	 * but in our judgement it is a wrong kind of savings, so clear it all.
+	 */
+	memset(ptr, 0, size);
+
 	codec->bank_base_playback = ptr;
 	codec->ctrl_playback = (u32 *)ptr;
 	codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES;
@@ -2301,7 +2298,6 @@
 	codec->codec_write = ymfpci_codec_write;
 
 	if (ac97_probe_codec(codec) == 0) {
-		/* Alan does not have this printout. P3 */
 		printk("ymfpci: ac97_probe_codec failed\n");
 		return -ENODEV;
 	}
@@ -2329,7 +2325,7 @@
 }
 
 /* */
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 # ifdef MODULE
 static int mpu_io     = 0;
 static int synth_io   = 0;
@@ -2339,7 +2335,7 @@
 static int mpu_io     = 0x330;
 static int synth_io   = 0x388;
 # endif
-#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
 /* */
 
 static int /* __init */
@@ -2357,17 +2353,17 @@
 
 	spin_lock_init(&codec->reg_lock);
 	spin_lock_init(&codec->voice_lock);
+	codec->open_sem = MUTEX;
 	codec->pci = pcidev;
-	codec->inst = instance;
 	codec->irq = pcidev->irq;
 	codec->device_id = pcidev->device;
-	pci_read_config_byte(pcidev, PCI_REVISION_ID, (u8 *)&codec->rev);
+	pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev);
 	codec->reg_area_phys = pcidev->base_address[0]&PCI_BASE_ADDRESS_MEM_MASK;
 	codec->reg_area_virt = (unsigned long)ioremap(codec->reg_area_phys, 0x8000);
 	pci_set_master(pcidev);
 
-	/* XXX KERN_INFO */
-	printk("ymfpci%d: %s at 0x%lx IRQ %d\n", instance,
+	/* Not printing instance number because we use dev_audio elsewhere. */
+	printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
 	    ymf_devv[devx].name, codec->reg_area_phys, codec->irq);
 
 	ymfpci_aclink_reset(pcidev);
@@ -2376,12 +2372,14 @@
 		return -ENODEV;
 	}
 
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
-	codec->iomidi = mpu_io;
-	codec->iosynth = synth_io;
-	if (ymfpci_setup_legacy(codec, pcidev) < 0) {
-		ymfpci_free(codec);
-		return -ENODEV;
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+	if (instance == 0) {
+		codec->iomidi = mpu_io;
+		codec->iosynth = synth_io;
+		if (ymfpci_setup_legacy(codec, pcidev) < 0) {
+			ymfpci_free(codec);
+			return -ENODEV;
+		}
 	}
 #endif
 
@@ -2397,15 +2395,15 @@
 	/* ymfpci_proc_init(card, codec); */
 
 	if (request_irq(codec->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
-		printk(KERN_ERR "ymfpci%d: unable to request IRQ %d\n",
-		    codec->inst, codec->irq);
+		printk(KERN_ERR "ymfpci: unable to request IRQ %d\n",
+		    codec->irq);
 		ymfpci_free(codec);
 		return -ENODEV;
 	}
 
 	/* register /dev/dsp */
 	if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) {
-		printk(KERN_ERR "ymfpci%d: unable to register dsp\n", codec->inst);
+		printk(KERN_ERR "ymfpci: unable to register dsp\n");
 		free_irq(codec->irq, codec);
 		ymfpci_free(codec);
 		return -ENODEV;
@@ -2421,9 +2419,7 @@
 		return err;
 	}
 
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
-	memset (&codec->opl3_data, 0, sizeof (struct address_info));
-	memset (&codec->mpu_data,  0, sizeof (struct address_info));
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 
 	codec->opl3_data.name = "ymfpci";
 	codec->mpu_data.name  = "ymfpci";
@@ -2432,16 +2428,14 @@
 	codec->opl3_data.irq     = -1;
 
 	codec->mpu_data.io_base  = codec->iomidi;
-	codec->mpu_data.irq      = -1;
+	codec->mpu_data.irq      = -1;	/* XXX Make it ours. */
 
-	if ( mpu_io > 0 )
-	{
-		if ( probe_uart401(&codec->mpu_data) ) {
+	if (codec->iomidi) {
+		if (probe_uart401(&codec->mpu_data)) {
 			attach_uart401(&codec->mpu_data);
 		}
 	}
-
-#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
 
 	codec->next = ymf_devs;
 	ymf_devs = codec;
@@ -2478,11 +2472,11 @@
 		unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer);
 		kfree(codec->ac97_codec[0]);
 	}
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 	if (codec->iomidi) {
 		unload_uart401(&(codec->mpu_data));
 	}
-#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
 	kfree(codec);
 }
 
diff -urN linux-2.2.19-pre5/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h
--- linux-2.2.19-pre5/drivers/sound/ymfpci.h	Mon Dec  3 20:56:35 2001
+++ linux/drivers/sound/ymfpci.h	Mon Dec  3 20:57:05 2001
@@ -131,13 +131,6 @@
 #define YDSXG_AC97READCMD		0x8000
 #define YDSXG_AC97WRITECMD		0x0000
 
-#define PCIR_VENDORID			0x00
-#define PCIR_DEVICEID			0x02
-#define PCIR_CMD			0x04
-#define PCIR_REVISIONID			0x08
-#define PCIR_BASEADDR			0x10
-#define PCIR_IRQ			0x3c
-
 #define PCIR_LEGCTRL			0x40
 #define PCIR_ELEGCTRL			0x42
 #define PCIR_DSXGCTRL			0x48
@@ -254,27 +247,27 @@
 	ymfpci_pcm_type_t type;
 	struct ymf_state *state;
 	ymfpci_voice_t *voices[2];	/* playback only */
-	int running;			// +
+	int running;
 	int spdif;
 };
 
 struct ymf_unit {
 	unsigned int device_id;	/* PCI device ID */
-	unsigned int rev;	/* PCI revision */
+	unsigned char rev;	/* PCI revision */
 	unsigned long reg_area_phys;
 	unsigned long reg_area_virt;
 
-	void *work_ptr;				// +
+	void *work_ptr;
 
 	unsigned int bank_size_playback;
 	unsigned int bank_size_capture;
 	unsigned int bank_size_effect;
 	unsigned int work_size;
 
-	void *bank_base_playback;		// +
-	void *bank_base_capture;		// +
-	void *bank_base_effect;			// +
-	void *work_base;			// +
+	void *bank_base_playback;
+	void *bank_base_capture;
+	void *bank_base_effect;
+	void *work_base;
 
 	u32 *ctrl_playback;
 	ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
@@ -291,20 +284,22 @@
 
 	struct pci_dev *pci;
 	int irq;
-	int inst;		/* Unit number (instance) */
 
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
         /* legacy hardware resources */
 	unsigned int iosynth, iomidi;
 	struct address_info opl3_data, mpu_data;
+#endif
 
 	spinlock_t reg_lock;
 	spinlock_t voice_lock;
 
 	/* soundcore stuff */
 	int dev_audio;
+	struct semaphore open_sem;
 
-	ymfpci_t *next;					// *
-	struct ymf_state *states[1];			// *
+	ymfpci_t *next;
+	struct ymf_state *states[1];
 	/* ypcm may be the same thing as state, but not for record, effects. */
 };
 
@@ -352,16 +347,12 @@
 struct ymf_state {
 	struct ymf_unit *unit;			/* backpointer */
 
-	/* single open lock mechanism, only used for recording */
-	struct semaphore open_sem;
-	struct wait_queue *open_wait;
-
 	/* virtual channel number */
 	int virt;				// * unused a.t.m.
 
-	struct ymf_pcm ypcm;			// *
-	struct ymf_dmabuf dmabuf;		// *
-	struct ymf_pcm_format format;		// *
+	struct ymf_pcm ypcm;
+	struct ymf_dmabuf dmabuf;
+	struct ymf_pcm_format format;
 };
 
 #endif				/* __YMFPCI_H */
diff -urN linux-2.2.19-pre5/fs/dcache.c linux/fs/dcache.c
--- linux-2.2.19-pre5/fs/dcache.c	Mon Dec  3 20:56:35 2001
+++ linux/fs/dcache.c	Mon Dec  3 20:57:05 2001
@@ -253,10 +253,15 @@
 
 		if (tmp == &dentry_unused)
 			break;
-		dentry_stat.nr_unused--;
 		list_del(tmp);
-		INIT_LIST_HEAD(tmp);
 		dentry = list_entry(tmp, struct dentry, d_lru);
+		if (dentry->d_flags & DCACHE_REFERENCED) {
+			dentry->d_flags &= ~DCACHE_REFERENCED;
+			list_add(&dentry->d_lru, &dentry_unused);
+			continue;
+		}
+		dentry_stat.nr_unused--;
+		INIT_LIST_HEAD(tmp);
 		if (!dentry->d_count) {
 			i_nr -= prune_one_dentry(dentry);
 			if (!i_nr)
@@ -598,6 +603,7 @@
 			if (memcmp(dentry->d_name.name, str, len))
 				continue;
 		}
+		dentry->d_flags |= DCACHE_REFERENCED;
 		return dget(dentry);
 	}
 	return NULL;
diff -urN linux-2.2.19-pre5/fs/dquot.c linux/fs/dquot.c
--- linux-2.2.19-pre5/fs/dquot.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/dquot.c	Mon Dec  3 20:57:05 2001
@@ -570,7 +570,7 @@
 	 */
 	if (prune_dcache(0, 128))
 	{
-		free_inode_memory(10);
+		free_inode_memory();
 		goto repeat;
 	}
 
diff -urN linux-2.2.19-pre5/fs/inode.c linux/fs/inode.c
--- linux-2.2.19-pre5/fs/inode.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/inode.c	Mon Dec  3 20:57:05 2001
@@ -435,7 +435,7 @@
  * This is the externally visible routine for
  * inode memory management.
  */
-void free_inode_memory(int goal)
+void free_inode_memory(void)
 {
 	spin_lock(&inode_lock);
 	free_inodes();
diff -urN linux-2.2.19-pre5/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h
--- linux-2.2.19-pre5/include/asm-alpha/mmu_context.h	Mon Aug  9 12:04:41 1999
+++ linux/include/asm-alpha/mmu_context.h	Mon Dec  3 20:57:05 2001
@@ -65,12 +65,7 @@
 #endif /* __SMP__ */
 
 #define WIDTH_HARDWARE_ASN	8
-#ifdef __SMP__
-#define WIDTH_THIS_PROCESSOR	5
-#else
-#define WIDTH_THIS_PROCESSOR	0
-#endif
-#define ASN_FIRST_VERSION (1UL << (WIDTH_THIS_PROCESSOR + WIDTH_HARDWARE_ASN))
+#define ASN_FIRST_VERSION (1UL << WIDTH_HARDWARE_ASN)
 #define HARDWARE_ASN_MASK ((1UL << WIDTH_HARDWARE_ASN) - 1)
 
 /*
@@ -100,6 +95,7 @@
 	/* If we've wrapped, flush the whole user TLB.  */
 	if ((asn & HARDWARE_ASN_MASK) >= MAX_ASN) {
 		tbiap();
+		imb();
 		next = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
 	}
 	cpu_last_asn(smp_processor_id()) = next;
@@ -125,19 +121,21 @@
 __EXTERN_INLINE void
 ev5_get_mmu_context(struct task_struct *p)
 {
-	/* Check if our ASN is of an older version, or on a different CPU,
-	   and thus invalid.  */
-	/* ??? If we have two threads on different cpus, we'll continually
-	   fight over the context.  Find a way to record a per-mm, per-cpu
-	   value for the asn.  */
-
-	unsigned long asn = cpu_last_asn(smp_processor_id());
-	struct mm_struct *mm = p->mm;
-	unsigned long mmc = mm->context;
+	/* Check if our ASN is of an older version, and thus invalid. */
+	int cpu;
+	unsigned long asn;
+	struct mm_struct *mm;
+	unsigned long mmc;
 	
+	cpu = smp_processor_id();
+	mm = p->mm;
+	ctx_cli();
+	asn = cpu_last_asn(cpu);
+	mmc = mm->context[cpu];
+
 	if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) {
 		mmc = __get_new_mmu_context();
-		mm->context = mmc;
+		mm->context[cpu] = mmc;
 	}
 
 	/* Always update the PCB ASN.  Another thread may have allocated
@@ -159,7 +157,10 @@
 extern inline void
 init_new_context(struct mm_struct *mm)
 {
-	mm->context = 0;
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		mm->context[cpu_logical_map(i)] = 0;
 }
 
 extern inline void
diff -urN linux-2.2.19-pre5/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- linux-2.2.19-pre5/include/asm-alpha/pgtable.h	Wed Jun  7 14:26:44 2000
+++ linux/include/asm-alpha/pgtable.h	Mon Dec  3 20:57:05 2001
@@ -73,7 +73,13 @@
 __EXTERN_INLINE void
 ev5_flush_tlb_other(struct mm_struct *mm)
 {
-	mm->context = 0;
+	long * mmc = &mm->context[smp_processor_id()];
+	/*
+	 * Check it's not zero first to avoid cacheline ping pong when
+	 * possible.
+	 */
+	if (*mmc)
+		*mmc = 0;
 }
 
 /*
diff -urN linux-2.2.19-pre5/include/asm-alpha/ptrace.h linux/include/asm-alpha/ptrace.h
--- linux-2.2.19-pre5/include/asm-alpha/ptrace.h	Mon Aug  9 12:05:05 1999
+++ linux/include/asm-alpha/ptrace.h	Mon Dec  3 20:57:05 2001
@@ -70,6 +70,7 @@
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
+extern void __show_regs(struct pt_regs *);
 #endif
 
 #endif
diff -urN linux-2.2.19-pre5/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h
--- linux-2.2.19-pre5/include/asm-alpha/softirq.h	Tue Jan  4 10:12:24 2000
+++ linux/include/asm-alpha/softirq.h	Mon Dec  3 20:57:05 2001
@@ -9,6 +9,7 @@
 extern unsigned long local_bh_count;
 #else
 #define local_bh_count          (cpu_data[smp_processor_id()].bh_count)
+extern spinlock_t alpha_bh_lock;
 #endif
 
 #define get_active_bhs()	(bh_mask & bh_active)
@@ -28,24 +29,6 @@
 	:"Ir" (x), "m" (bh_active));
 }
 
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-	bh_base[nr] = NULL;
-	bh_mask &= ~(1 << nr);
-}
-
-extern inline void mark_bh(int nr)
-{
-	set_bit(nr, &bh_active);
-}
-
 #ifdef __SMP__
 
 /*
@@ -113,21 +96,58 @@
 
 #endif	/* SMP */
 
+extern inline void init_bh(int nr, void (*routine)(void))
+{
+	unsigned long flags;
+
+	bh_base[nr] = routine;
+	atomic_set(&bh_mask_count[nr], 0);
+
+	spin_lock_irqsave(&alpha_bh_lock, flags);
+	bh_mask |= 1 << nr;
+	spin_unlock_irqrestore(&alpha_bh_lock, flags);
+}
+
+extern inline void remove_bh(int nr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&alpha_bh_lock, flags);
+	bh_mask &= ~(1 << nr);
+	spin_unlock_irqrestore(&alpha_bh_lock, flags);
+
+	synchronize_bh();
+	bh_base[nr] = NULL;
+}
+
+extern inline void mark_bh(int nr)
+{
+	set_bit(nr, &bh_active);
+}
+
 /*
  * These use a mask count to correctly handle
  * nested disable/enable calls
  */
 extern inline void disable_bh(int nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&alpha_bh_lock, flags);
 	bh_mask &= ~(1 << nr);
 	atomic_inc(&bh_mask_count[nr]);
+	spin_unlock_irqrestore(&alpha_bh_lock, flags);
 	synchronize_bh();
 }
 
 extern inline void enable_bh(int nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&alpha_bh_lock, flags);
 	if (atomic_dec_and_test(&bh_mask_count[nr]))
 		bh_mask |= 1 << nr;
+	spin_unlock_irqrestore(&alpha_bh_lock, flags);
 }
 
 #endif /* _ALPHA_SOFTIRQ_H */
diff -urN linux-2.2.19-pre5/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h
--- linux-2.2.19-pre5/include/asm-alpha/spinlock.h	Tue Jan  4 10:12:24 2000
+++ linux/include/asm-alpha/spinlock.h	Mon Dec  3 20:57:05 2001
@@ -231,6 +231,7 @@
 static inline void read_unlock(rwlock_t * lock)
 {
 	long regx;
+	mb();
 	__asm__ __volatile__(
 	"1:	ldl_l	%1,%0\n"
 	"	addl	%1,2,%1\n"
diff -urN linux-2.2.19-pre5/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- linux-2.2.19-pre5/include/asm-alpha/system.h	Sun Dec 10 16:49:44 2000
+++ linux/include/asm-alpha/system.h	Mon Dec  3 20:57:05 2001
@@ -112,12 +112,21 @@
 
 extern void halt(void) __attribute__((noreturn));
 
+#ifdef CONFIG_SMP
+#define ctx_cli()	__cli()
+#define ctx_sti()	__sti()
+#else
+#define ctx_cli()	do { } while(0)
+#define ctx_sti()	do { } while(0)
+#endif
+
 #define switch_to(prev,next,last)			\
 do {							\
 	unsigned long pcbb;				\
 	current = (next);				\
 	pcbb = virt_to_phys(&current->tss);		\
 	(last) = alpha_switch_to(pcbb, (prev));		\
+	ctx_sti();					\
 } while (0)
 
 extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*);
diff -urN linux-2.2.19-pre5/include/linux/dcache.h linux/include/linux/dcache.h
--- linux-2.2.19-pre5/include/linux/dcache.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/dcache.h	Mon Dec  3 20:57:05 2001
@@ -106,6 +106,10 @@
 					 * If this dentry points to a directory, then
 					 * s_nfsd_free_path semaphore will be down
 					 */
+#define	DCACHE_REFERENCED 0x0008	/* This dentry is been recently
+					 * referenced so try to keep it in
+					 * cache.
+					 */
 
 /*
  * d_drop() unhashes the entry from the parent
@@ -149,7 +153,7 @@
 /* dcache memory management */
 extern void shrink_dcache_memory(int, unsigned int);
 extern void check_dcache_memory(void);
-extern void free_inode_memory(int);	/* defined in fs/inode.c */
+extern void free_inode_memory(void);	/* defined in fs/inode.c */
 
 /* only used at mount-time */
 extern struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root);
diff -urN linux-2.2.19-pre5/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.2.19-pre5/include/linux/sched.h	Mon Dec  3 20:56:36 2001
+++ linux/include/linux/sched.h	Mon Dec  3 20:57:05 2001
@@ -181,7 +181,11 @@
 	atomic_t count;
 	int map_count;				/* number of VMAs */
 	struct semaphore mmap_sem;
+#ifdef __alpha__
+	unsigned long context[NR_CPUS];
+#else
 	unsigned long context;
+#endif
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
@@ -197,12 +201,18 @@
 	void * segments;
 };
 
+#ifdef __alpha__
+#define CONTEXT_INIT	{ 0, }
+#else
+#define CONTEXT_INIT	0
+#endif
+
 #define INIT_MM {					\
 		&init_mmap, NULL, NULL,			\
 		swapper_pg_dir, 			\
 		ATOMIC_INIT(1), 1,			\
 		MUTEX,					\
-		0,					\
+		CONTEXT_INIT,				\
 		0, 0, 0, 0,				\
 		0, 0, 0, 				\
 		0, 0, 0, 0,				\
