]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.19pre6 2.2.19pre6
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:08 +0000 (15:23 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:08 +0000 (15:23 -0500)
o Yamaha PCI sound updates (Pete Zaitcev)
o Alpha SMP ASN reuse races (Andrea Arcangeli)
o Alpha bottom half SMP race fixes (Andrea Arcangeli)
o Alpha SMP read_unloc race fix (Andrea Arcangeli)
o Show registers across CPUs on SMP alpha death (Andrea Arcangeli)
o Print the 8K of stack not the top 4K on x86 (Andrea Arcangeli)
o Dcache aging (Andrea Arcangeli)
o Kill unused parameter in free_inode_memory (Andrea Arcangeli)

23 files changed:
Makefile
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/irq.c
arch/alpha/kernel/process.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/traps.c
arch/alpha/mm/fault.c
arch/i386/kernel/traps.c
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/ymfpci.c
drivers/sound/ymfpci.h
fs/dcache.c
fs/dquot.c
fs/inode.c
include/asm-alpha/mmu_context.h
include/asm-alpha/pgtable.h
include/asm-alpha/ptrace.h
include/asm-alpha/softirq.h
include/asm-alpha/spinlock.h
include/asm-alpha/system.h
include/linux/dcache.h
include/linux/sched.h

index 7923e783109d5a43028b80a5c6df7fdf39b4760b..65a84aaeb7d560ff915816d0f92ab4f690e0a143 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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/)
 
index 3809345b34bc10d77e1915d151b9c1da342741c9..40f0c40bb662285c5510e69040bc0b67d7906603 100644 (file)
@@ -169,6 +169,7 @@ EXPORT_SYMBOL(cpu_number_map);
 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);
index 776b9ca4ce9b086223d7fad0aca218a3ec0f5611..2f5858d64b1af4941b7541baa0c4fb7bcb6a78bf 100644 (file)
@@ -385,6 +385,7 @@ atomic_t global_irq_count = ATOMIC_INIT(0);
 /* 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 @@ wait_on_bh(void)
 void
 synchronize_bh(void)
 {
+       mb();
        if (atomic_read(&global_bh_count) && !in_interrupt())
                        wait_on_bh();
 }
index 9c30d834424922d21eec11ee8f9e95374a1a63e4..e7ff1e47d40333a4dea81628f0297e8e41449ac2 100644 (file)
@@ -249,8 +249,11 @@ void machine_power_off(void)
        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 @@ void show_regs(struct pt_regs * regs)
               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
 }
 
 /*
index 646c3c19a2003221dc762a39be60f8f5aaeedfc5..cc35a8dd64ab6a4edb1dd7ab2a9a6c630ea591bf 100644 (file)
@@ -95,8 +95,7 @@ static inline void __init
 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 @@ handle_ipi(struct pt_regs *regs)
 
                        /* 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();
@@ -855,6 +861,21 @@ smp_imb(void)
        imb();
 }
 
+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)
 {
@@ -879,6 +900,8 @@ ipi_flush_tlb_mm(void *x)
        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 @@ flush_tlb_mm(struct mm_struct *mm)
 {
        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 @@ static void
 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 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
 
        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;
index 655582653f672aaef60c742c9a1fe889adbd7c02..4934483e01c3148f9d90674af5e4a76254cc81f9 100644 (file)
@@ -269,7 +269,7 @@ dik_show_code(unsigned int *pc)
        }
 }
 
-static void
+void
 dik_show_trace(unsigned long *sp)
 {
        int i = 1;
index df1f2ae659bd1c0994cd49388e2a837bc0a09c21..443a6bd2ad223144793d622944d08cf16d85ed2b 100644 (file)
@@ -41,7 +41,7 @@ void
 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;
 }
 
index 5bd458b0b74c73f74c6186652286d9dd69d3e7bd..3869f2ab42ba7e6a28341570641374b6dda3948b 100644 (file)
@@ -155,7 +155,7 @@ static void show_registers(struct pt_regs *regs)
                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 @@ static void show_registers(struct pt_regs *regs)
                        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
index da8bfebb2ccbcb60f8e7eea0fa11f197054fe614..a58192ce8cc19895614aec0a5de30c6747516885 100644 (file)
@@ -312,7 +312,10 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
   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.
   
index fe620bc221cd227cf3f37d46ccef2368a9f2881e..5e0c5c0a737d63089a212672a7144e3731bb9b77 100644 (file)
@@ -98,7 +98,10 @@ obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o
 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
index b4a625a8c5b1435e55f7f123717b751226bc2a42..b108fae3468edfaac67eb8a914e24e443b56f1e1 100644 (file)
@@ -34,8 +34,6 @@
  *      ? underused structure members
  */
 
-#define YMFPCI_HAVE_MIDI_SUPPORT
-
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #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 @@ static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
     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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
        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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
 
                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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                                 */
                                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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                                 */
 //                             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 @@ static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd)
 {
 
        if (ypcm->voices[0] == NULL) {
-/* P3 */ printk("ymfpci: trigger %d no voice\n", cmd);
                return -EINVAL;
        }
        if (cmd != 0) {
@@ -832,8 +826,8 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
                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 @@ static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state)
        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 @@ void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        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 void ymf_pcm_free_substream(ymfpci_pcm_t *ypcm)
        }
 }
 
-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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
 
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
         */
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
 
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                                dmabuf->ready = 0;
                        }
 #endif
-                       spin_unlock_irqrestore(&state->unit->reg_lock, flags);
                }
                return put_user(state->format.voices, (int *)arg);
 
@@ -1696,7 +1691,6 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                 * 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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
 #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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
 #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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        return -ENOTTY;
 }
 
-#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
 /* MIDI stuff */
 
 /* */
@@ -1939,10 +1928,10 @@ static int ymfpci_setup_legacy( ymfpci_t *codec, struct pci_dev *pcidev )
                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 @@ static int ymfpci_setup_legacy( ymfpci_t *codec, struct pci_dev *pcidev )
 
        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 @@ static int ymf_open(struct inode *inode, struct file *file)
        } 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 @@ static int ymf_open(struct inode *inode, struct file *file)
        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 @@ static int ymf_open(struct inode *inode, struct file *file)
                unit->states[state->virt] = NULL;
                kfree(state);
 
+               up(&unit->open_sem);
                return err;
        }
 
@@ -2027,6 +2014,9 @@ static int ymf_open(struct inode *inode, struct file *file)
            (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 @@ static int ymf_release(struct inode *inode, struct file *file)
        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 @@ static int ymf_release(struct inode *inode, struct file *file)
        codec->states[state->virt] = NULL;
        kfree(state);
 
+       up(&codec->open_sem);
+
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2151,8 +2143,7 @@ static void ymfpci_disable_dsp(ymfpci_t *codec)
        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 @@ static int ymfpci_memalloc(ymfpci_t *codec)
        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 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
        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 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
 }
 
 /* */
-#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 @@ MODULE_PARM(synth_io, "i");
 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 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
 
        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 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
                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 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
        /* 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 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
                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 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
        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 @@ ymfpci_free(ymfpci_t *codec)
                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);
 }
 
index 0f0b674eebe85bc77cd5dce7bba08c97bb5b3fdf..07cdcd9cf4f2696aafe484a1a93e67bc7189c158 100644 (file)
 #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 @@ struct ymf_pcm {
        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 ymf_unit {
 
        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_pcm_format {
 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 */
index e4265a5ce0534fbf3987b4b62fcc4d72ebb1c228..e32f5b711cde40948b4d287472483a08e0c99f40 100644 (file)
@@ -253,10 +253,15 @@ int prune_dcache(int d_nr, int i_nr)
 
                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 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
                        if (memcmp(dentry->d_name.name, str, len))
                                continue;
                }
+               dentry->d_flags |= DCACHE_REFERENCED;
                return dget(dentry);
        }
        return NULL;
index a4a986f447d707b4f6b02e63258b2e50f3549a0b..fd897f251372863f96c89903f74edbc196346908 100644 (file)
@@ -570,7 +570,7 @@ pressure:
         */
        if (prune_dcache(0, 128))
        {
-               free_inode_memory(10);
+               free_inode_memory();
                goto repeat;
        }
 
index 1c44af8de6f1aaeece3fd24e834328d9caa24f5c..d6c141bd8cc5f5579148763495026013beb91b34 100644 (file)
@@ -435,7 +435,7 @@ static void try_to_free_inodes(int goal)
  * 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();
index 140cc28bc3b40803519e09288d2a00369ff3933b..194a7807291d360abb89061c613d829eb37adaea 100644 (file)
@@ -65,12 +65,7 @@ extern unsigned long last_asn;
 #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 @@ __get_new_mmu_context(void)
        /* 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 @@ ev4_get_mmu_context(struct task_struct *p)
 __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 @@ ev5_get_mmu_context(struct task_struct *p)
 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
index b881d0e16b0acd0a4693f5908f1a061e1f2bc9d3..6a59ed6e7800db20f28a252ae330dcca66ab7fdb 100644 (file)
@@ -73,7 +73,13 @@ ev5_flush_tlb_current(struct mm_struct *mm)
 __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;
 }
 
 /*
index 268ebfced8e2c8548cdbaef23dcac01b184c8185..45cbb55ae25e333a15bf3f4f77b0053d7caf8a8d 100644 (file)
@@ -70,6 +70,7 @@ struct switch_stack {
 #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
index 8dd4f644866b403b63115a9bb64662e0b2b9c70a..8aaca4a058c2a432ac45856158ce01e6fc7f5779 100644 (file)
@@ -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 @@ static inline void clear_active_bhs(unsigned long x)
        :"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 @@ extern inline void end_bh_atomic(void)
 
 #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 */
index 645a025b28e65fb59af4ec072c2071186f1088ae..449f23ee3cab4c2577bfb3bdefb438edc7832b82 100644 (file)
@@ -231,6 +231,7 @@ static inline void write_unlock(rwlock_t * lock)
 static inline void read_unlock(rwlock_t * lock)
 {
        long regx;
+       mb();
        __asm__ __volatile__(
        "1:     ldl_l   %1,%0\n"
        "       addl    %1,2,%1\n"
index c748674690120a0177e8c00678dda081159476af..063addc58a9e1c266afda2726f6f19ab7d2b5fed 100644 (file)
@@ -112,12 +112,21 @@ struct el_common_EV6_mcheck {
 
 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*);
index 6c725d4d0d739b66a34a664bfe97ac45715b35ac..b49f508206ea851a7ff64e87e382175cc8e91fe5 100644 (file)
@@ -106,6 +106,10 @@ struct dentry_operations {
                                         * 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 @@ extern int d_invalidate(struct dentry *);
 /* 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);
index 4dde45a2f153218c0eeaec40cbb9e6511e960194..ec23523b95f1663d0703526cc578492bc733406d 100644 (file)
@@ -181,7 +181,11 @@ struct mm_struct {
        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 @@ struct mm_struct {
        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,                             \