From: Alan Cox Date: Fri, 23 Nov 2007 20:23:08 +0000 (-0500) Subject: Linux 2.2.19pre6 X-Git-Tag: 2.2.19pre6 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=3cae0df9df2ed46cd3dd425e448928564b5a2a07;p=history.git Linux 2.2.19pre6 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) --- diff --git a/Makefile b/Makefile index 7923e783109d..65a84aaeb7d5 100644 --- 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/) diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 3809345b34bc..40f0c40bb662 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -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); diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 776b9ca4ce9b..2f5858d64b1a 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -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(); } diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 9c30d8344249..e7ff1e47d403 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -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 } /* diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 646c3c19a200..cc35a8dd64ab 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -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(¤t->mm->count) == 1) + if (atomic_read(¤t->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 --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 655582653f67..4934483e01c3 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -269,7 +269,7 @@ dik_show_code(unsigned int *pc) } } -static void +void dik_show_trace(unsigned long *sp) { int i = 1; diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index df1f2ae659bd..443a6bd2ad22 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -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; } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 5bd458b0b74c..3869f2ab42ba 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -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 diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index da8bfebb2ccb..a58192ce8cc1 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -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. diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index fe620bc221cd..5e0c5c0a737d 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -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 diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c index b4a625a8c5b1..b108fae3468e 100644 --- a/drivers/sound/ymfpci.c +++ b/drivers/sound/ymfpci.c @@ -34,8 +34,6 @@ * ? underused structure members */ -#define YMFPCI_HAVE_MIDI_SUPPORT - #include #include #include @@ -48,10 +46,9 @@ #include #include -#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); } diff --git a/drivers/sound/ymfpci.h b/drivers/sound/ymfpci.h index 0f0b674eebe8..07cdcd9cf4f2 100644 --- a/drivers/sound/ymfpci.h +++ b/drivers/sound/ymfpci.h @@ -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 @@ 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 */ diff --git a/fs/dcache.c b/fs/dcache.c index e4265a5ce053..e32f5b711cde 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -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; diff --git a/fs/dquot.c b/fs/dquot.c index a4a986f447d7..fd897f251372 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -570,7 +570,7 @@ pressure: */ if (prune_dcache(0, 128)) { - free_inode_memory(10); + free_inode_memory(); goto repeat; } diff --git a/fs/inode.c b/fs/inode.c index 1c44af8de6f1..d6c141bd8cc5 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -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(); diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index 140cc28bc3b4..194a7807291d 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -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 diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index b881d0e16b0a..6a59ed6e7800 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -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; } /* diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index 268ebfced8e2..45cbb55ae25e 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h @@ -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 diff --git a/include/asm-alpha/softirq.h b/include/asm-alpha/softirq.h index 8dd4f644866b..8aaca4a058c2 100644 --- a/include/asm-alpha/softirq.h +++ b/include/asm-alpha/softirq.h @@ -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 */ diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h index 645a025b28e6..449f23ee3cab 100644 --- a/include/asm-alpha/spinlock.h +++ b/include/asm-alpha/spinlock.h @@ -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" diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index c74867469012..063addc58a9e 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -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(¤t->tss); \ (last) = alpha_switch_to(pcbb, (prev)); \ + ctx_sti(); \ } while (0) extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 6c725d4d0d73..b49f508206ea 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -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); diff --git a/include/linux/sched.h b/include/linux/sched.h index 4dde45a2f153..ec23523b95f1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -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, \