diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-13 20:55:15 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-13 20:55:15 +0000 |
commit | 1471f525455788c20b130690e0f104df451aeb43 (patch) | |
tree | 3778beba56558beb9a9548ea5b467e9c44ea966f /arch | |
parent | e80d2c5456d30ebba5b0eb8a9d33e17d815d4d83 (diff) |
Merge with Linux 2.3.51.
Diffstat (limited to 'arch')
79 files changed, 1857 insertions, 1516 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 1686fefbc..6e760c917 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -270,7 +270,7 @@ source drivers/char/Config.in source drivers/usb/Config.in -source drivers/misc/Config.in +#source drivers/misc/Config.in source fs/Config.in diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 9365dc4e2..cc244e560 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -324,10 +324,6 @@ CONFIG_PSMOUSE=y # CONFIG_USB is not set # -# Misc devices -# - -# # Filesystems # # CONFIG_QUOTA is not set diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 6a2ff8a9b..091edaf37 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -303,18 +303,9 @@ static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz) { struct statfs linux_stat; - struct inode * inode = dentry->d_inode; - struct super_block * sb = inode->i_sb; - int error; - - error = -ENODEV; - if (sb && sb->s_op && sb->s_op->statfs) { - set_fs(KERNEL_DS); - error = sb->s_op->statfs(sb, &linux_stat, sizeof(linux_stat)); - set_fs(USER_DS); - if (!error) - error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); - } + int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat); + if (!error) + error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; } diff --git a/arch/arm/Makefile b/arch/arm/Makefile index bb0a34f92..6b4033705 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -12,7 +12,6 @@ # # Copyright (C) 1995-1999 by Russell King -LD := $(CROSS_COMPILE)ld OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S CPP := $(CC) -E PERL := perl diff --git a/arch/arm/config.in b/arch/arm/config.in index 5e9cc8bfc..4c7a5fe19 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -214,7 +214,7 @@ fi source drivers/usb/Config.in -source drivers/misc/Config.in +#source drivers/misc/Config.in if [ "$CONFIG_VT" = "y" ]; then mainmenu_option next_comment diff --git a/arch/i386/config.in b/arch/i386/config.in index 11a98fc58..e1ba021e1 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -50,9 +50,7 @@ if [ "$CONFIG_MK7" = "y" ]; then define_bool CONFIG_X86_PGE y fi -if [ "$CONFIG_DEVFS_FS" = "y" ]; then - tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE -fi +tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE choice 'High Memory Support' \ "off CONFIG_NOHIGHMEM \ @@ -142,7 +140,7 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Power Management support' CONFIG_PM -dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM +dep_tristate ' ACPI support' CONFIG_ACPI $CONFIG_PM if [ "$CONFIG_ACPI" != "n" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP @@ -231,7 +229,7 @@ source drivers/char/Config.in source drivers/usb/Config.in -source drivers/misc/Config.in +#source drivers/misc/Config.in source fs/Config.in diff --git a/arch/i386/defconfig b/arch/i386/defconfig index aa04c3685..813a2ecea 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -27,6 +27,7 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_PGE=y +# CONFIG_MICROCODE is not set CONFIG_NOHIGHMEM=y # CONFIG_HIGHMEM4G is not set # CONFIG_HIGHMEM64G is not set @@ -165,6 +166,7 @@ CONFIG_SKB_LARGE=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # # Telephony Support @@ -197,6 +199,7 @@ CONFIG_SCSI_CONSTANTS=y # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -334,7 +337,6 @@ CONFIG_PCMCIA_PCNET=y # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_AIRONET4500_CS is not set # CONFIG_ARCNET_COM20020_CS is not set # CONFIG_PCMCIA_3C575 is not set # CONFIG_PCMCIA_TULIP is not set @@ -342,6 +344,7 @@ CONFIG_NET_PCMCIA_RADIO=y CONFIG_PCMCIA_RAYCS=y # CONFIG_PCMCIA_NETWAVE is not set # CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_AIRONET4500_CS is not set CONFIG_PCMCIA_NETCARD=y # @@ -402,7 +405,6 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -433,10 +435,6 @@ CONFIG_PCMCIA_SERIAL=y # CONFIG_USB is not set # -# Misc devices -# - -# # File systems # # CONFIG_QUOTA is not set diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c index b19097420..d95bbe6b1 100644 --- a/arch/i386/kernel/acpi.c +++ b/arch/i386/kernel/acpi.c @@ -50,7 +50,6 @@ */ extern unsigned long get_cmos_time(void); -static int acpi_control_thread(void *context); static int acpi_do_ulong(ctl_table *ctl, int write, struct file *file, @@ -72,8 +71,6 @@ static int acpi_do_sleep(ctl_table *ctl, void *buffer, size_t *len); -DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait); - static struct ctl_table_header *acpi_sysctl = NULL; static struct acpi_facp *acpi_facp = NULL; @@ -105,7 +102,15 @@ static unsigned long acpi_p_blk = 0; static int acpi_p_lvl2_tested = 0; static int acpi_p_lvl3_tested = 0; -static int acpi_disabled = 0; +enum +{ + ACPI_ENABLED, + ACPI_TABLES_ONLY, + ACPI_CHIPSET_ONLY, + ACPI_DISABLED, +}; + +static int acpi_enabled = ACPI_ENABLED; // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb static unsigned long acpi_slp_typ[] = @@ -1296,13 +1301,21 @@ static int acpi_do_sleep(ctl_table *ctl, */ static int __init acpi_init(void) { - int pid; - - if (acpi_disabled) - return -ENODEV; - - if (acpi_find_tables() && acpi_find_chipset()) { - // no ACPI tables and not recognized chipset + switch(acpi_enabled) + { + case ACPI_ENABLED: + if (acpi_find_tables() && acpi_find_chipset()) + return -ENODEV; + break; + case ACPI_TABLES_ONLY: + if (acpi_find_tables()) + return -ENODEV; + break; + case ACPI_CHIPSET_ONLY: + if (acpi_find_chipset()) + return -ENODEV; + break; + case ACPI_DISABLED: return -ENODEV; } @@ -1342,10 +1355,6 @@ static int __init acpi_init(void) acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); - pid = kernel_thread(acpi_control_thread, - NULL, - CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - pm_power_off = acpi_power_off; pm_active = 1; @@ -1379,6 +1388,7 @@ err_out: static void __exit acpi_exit(void) { pm_idle = NULL; + pm_active = 0; pm_power_off = NULL; unregister_sysctl_table(acpi_sysctl); @@ -1400,10 +1410,14 @@ static void __exit acpi_exit(void) static int __init acpi_setup(char *str) { while (str && *str) { - if (strncmp(str, "off", 3) == 0) - acpi_disabled = 1; - else if (strncmp(str, "on", 2) == 0) - acpi_disabled = 0; + if (strncmp(str, "on", 2) == 0) + acpi_enabled = ACPI_ENABLED; + else if (strncmp(str, "tables", 6) == 0) + acpi_enabled = ACPI_TABLES_ONLY; + else if (strncmp(str, "chipset", 7) == 0) + acpi_enabled = ACPI_CHIPSET_ONLY; + else if (strncmp(str, "off", 3) == 0) + acpi_enabled = ACPI_DISABLED; str = strpbrk(str, ","); if (str) str += strspn(str, ","); @@ -1413,24 +1427,5 @@ static int __init acpi_setup(char *str) __setup("acpi=", acpi_setup); -/* - * Manage idle devices - */ -static int acpi_control_thread(void *context) -{ - exit_mm(current); - exit_files(current); - strcpy(current->comm, "acpi"); - - for(;;) { - interruptible_sleep_on(&acpi_control_wait); - if (signal_pending(current)) - break; - - // find all idle devices and set idle timer - } - - return 0; -} - -__initcall(acpi_init); +module_init(acpi_init); +module_exit(acpi_exit); diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 3d403b93c..99e258756 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -590,11 +590,11 @@ static void apm_cpu_idle(void) continue; if (hlt_counter) continue; - asm volatile("cli" : : : "memory"); + __cli(); if (!current->need_resched) - asm volatile("sti ; hlt" : : : "memory"); + safe_halt(); else - asm volatile("sti" : : : "memory"); + __sti(); continue; } diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c index a76c92d25..e51e96e43 100644 --- a/arch/i386/kernel/pci-pc.c +++ b/arch/i386/kernel/pci-pc.c @@ -1044,17 +1044,17 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt) printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i); } -static void set_level_irq(unsigned irq) +static void ali_set_level_irq(unsigned irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); if (val & mask) { - printk("PCI irq %d was level\n", irq); + DBG("PCI irq %d was level\n", irq); return; } - printk("PCI irq %d was edge, turning into level-triggered\n", irq); + DBG("PCI irq %d was edge, turning into level-triggered\n", irq); outb(val | mask, port); } @@ -1070,18 +1070,17 @@ static int ali_set_irq(struct pci_dev *router, unsigned pirq, unsigned irq) unsigned offset = 0x48 + (pirq >> 1); unsigned shift = (pirq & 1) << 2; pci_read_config_byte(router, offset, &byte); - printk("ALI: old %04x=%02x\n", offset, byte); + DBG("ALI: old %04x=%02x\n", offset, byte); byte &= ~(0xf << shift); byte |= val << shift; - printk("ALI: new %04x=%02x\n", offset, byte); + DBG("ALI: new %04x=%02x\n", offset, byte); pci_write_config_byte(router, offset, byte); - set_level_irq(irq); + ali_set_level_irq(irq); return irq; } } return 0; } - /* * In case BIOS forgets to tell us about IRQ, we try to look it up in the routing @@ -1380,13 +1379,17 @@ int pcibios_enable_device(struct pci_dev *dev) if ((err = pcibios_enable_resources(dev)) < 0) return err; - if (!dev->irq && pirq_table) { + if (!dev->irq) { u8 pin; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin) { - char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 1); - if (msg) + char *msg; + if (pirq_table && ((msg = pcibios_lookup_irq(dev, pirq_table, pin, 1)))) printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg); + else + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", + 'A' + pin - 1, dev->slot_name, + (pci_probe & PCI_BIOS_IRQ_SCAN) ? "" : " Please try using pci=biosirq."); } } return 0; diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index a043b4cfe..3ba1d8257 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -75,11 +75,11 @@ void enable_hlt(void) static void default_idle(void) { if (current_cpu_data.hlt_works_ok && !hlt_counter) { - asm volatile("cli" : : : "memory"); + __cli(); if (!current->need_resched) - asm volatile("sti ; hlt" : : : "memory"); + safe_halt(); else - asm volatile("sti" : : : "memory"); + __sti(); } } diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 24e274aa0..3ace288ef 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -5,7 +5,7 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1998, 1999 by David Mosberger-Tang <davidm@hpl.hp.com> +# Copyright (C) 1998-2000 by David Mosberger-Tang <davidm@hpl.hp.com> # NM := $(CROSS_COMPILE)nm -B @@ -14,12 +14,12 @@ LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds # next line is for HP compiler backend: #AFLAGS += -DGCC_RETVAL_POINTER_IN_R8 # The next line is needed when compiling with the July snapshot of the Cygnus compiler: -#EXTRA = -ma0-bugs -D__GCC_DOESNT_KNOW_IN_REGS__ +#EXTRA = -D__GCC_DOESNT_KNOW_IN_REGS__ # next two lines are for the September snapshot of the Cygnus compiler: AFLAGS += -D__GCC_MULTIREG_RETVALS__ -EXTRA = -ma0-bugs -D__GCC_MULTIREG_RETVALS__ +EXTRA = -D__GCC_MULTIREG_RETVALS__ -CFLAGS := -g $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 +CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 ifdef CONFIG_IA64_GENERIC CORE_FILES := arch/$(ARCH)/hp/hp.a \ diff --git a/arch/ia64/config.in b/arch/ia64/config.in index 2d2388590..3d1dd7e02 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -35,7 +35,7 @@ if [ "$CONFIG_IA64_SGI_SN1_SIM" = "y" ]; then define_bool CONFIG_IA64_SOFTSDV_HACKS y fi -define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /dev/kcore. +define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore. bool 'SMP support' CONFIG_SMP n bool 'Performance monitor support' CONFIG_PERFMON n @@ -123,7 +123,7 @@ endmenu source drivers/char/Config.in source drivers/usb/Config.in -source drivers/misc/Config.in +#source drivers/misc/Config.in source fs/Config.in diff --git a/arch/ia64/dig/iosapic.c b/arch/ia64/dig/iosapic.c index 6a392226e..4861aa2d9 100644 --- a/arch/ia64/dig/iosapic.c +++ b/arch/ia64/dig/iosapic.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/pci.h> #include <linux/smp.h> #include <linux/smp_lock.h> @@ -19,7 +20,6 @@ #include <asm/io.h> #include <asm/iosapic.h> -#include <asm/irq.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/delay.h> @@ -258,6 +258,21 @@ disable_pin (unsigned int pin, unsigned long iosapic_addr) #define iosapic_shutdown_irq iosapic_disable_irq +static unsigned int +iosapic_startup_irq (unsigned int irq) +{ + int pin; + + pin = iosapic_pin(irq); + if (pin < 0) + /* happens during irq auto probing... */ + return 0; + set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), + iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq); + enable_pin(pin, iosapic_addr(irq)); + return 0; +} + static void iosapic_enable_irq (unsigned int irq) { @@ -295,58 +310,26 @@ iosapic_version(unsigned long base_addr) return readl(IO_SAPIC_WINDOW + base_addr); } -static int -iosapic_handle_irq (unsigned int irq, struct pt_regs *regs) +static void +iosapic_ack_irq (unsigned int irq) { - struct irqaction *action = 0; - struct irq_desc *id = irq_desc + irq; - unsigned int status; - int retval; - - spin_lock(&irq_controller_lock); - { - status = id->status; - - /* do we need to do something IOSAPIC-specific to ACK the irq here??? */ - /* Yes, but only level-triggered interrupts. We'll do that later */ - if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) { - action = id->action; - status |= IRQ_INPROGRESS; - } - id->status = status & ~(IRQ_REPLAY | IRQ_WAITING); - } - spin_unlock(&irq_controller_lock); - - if (!action) { - if (!(id->status & IRQ_AUTODETECT)) - printk("iosapic_handle_irq: unexpected interrupt %u;" - "disabling it (status=%x)\n", irq, id->status); - /* - * If we don't have a handler, disable the pin so we - * won't get any further interrupts (until - * re-enabled). --davidm 99/12/17 - */ - iosapic_disable_irq(irq); - return 0; - } - - retval = invoke_irq_handlers (irq, regs, action); +} +static void +iosapic_end_irq (unsigned int irq) +{ if (iosapic_trigger(irq) == IO_SAPIC_LEVEL) /* ACK Level trigger interrupts */ writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI); +} - spin_lock(&irq_controller_lock); - { - status = (id->status & ~IRQ_INPROGRESS); - id->status = status; - } - spin_unlock(&irq_controller_lock); - - return retval; +static void +iosapic_set_affinity (unsigned int irq, unsigned long mask) +{ + printk("iosapic_set_affinity: not implemented yet\n"); } -void __init -iosapic_init (unsigned long addr) +void +iosapic_init (unsigned long address) { int i; #ifdef CONFIG_IA64_IRQ_ACPI @@ -357,18 +340,9 @@ iosapic_init (unsigned long addr) #endif /* - * Disable all local interrupts - */ - - ia64_set_itv(0, 1); - ia64_set_lrr0(0, 1); - ia64_set_lrr1(0, 1); - - /* * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support * enabled. */ - outb(0xff, 0xA1); outb(0xff, 0x21); @@ -376,10 +350,13 @@ iosapic_init (unsigned long addr) memset(iosapic_vector, 0x0, sizeof(iosapic_vector)); for (i = 0; i < NR_IRQS; i++) { iosapic_pin(i) = 0xff; - iosapic_addr(i) = (unsigned long) ioremap(IO_SAPIC_DEFAULT_ADDR, 0); + iosapic_addr(i) = (unsigned long) ioremap(address, 0); } /* XXX this should come from systab or some such: */ +# if 0 + /* this doesn't look right --davidm 00/03/07 */ iosapic_pin(TIMER_IRQ) = 5; /* System Clock Interrupt */ +# endif iosapic_pin(0x40) = 3; /* Keyboard */ iosapic_pin(0x92) = 9; /* COM1 Serial Port */ iosapic_pin(0x80) = 4; /* Periodic Interrupt */ @@ -396,7 +373,7 @@ iosapic_init (unsigned long addr) i = -1; while (intr_routing[++i].srcbus != 0xff) { if (intr_routing[i].srcbus == BUS_ISA) { - vector = map_legacy_irq(intr_routing[i].srcbusirq); + vector = isa_irq_to_vector(intr_routing[i].srcbusirq); } else if (intr_routing[i].srcbus == BUS_PCI) { vector = intr_routing[i].iosapic_pin; } else { @@ -414,7 +391,7 @@ iosapic_init (unsigned long addr) iosapic_trigger(vector)); # endif } -#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && !defined(CONFIG_IA64_IRQ_ACPI) */ +#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_IA64_IRQ_ACPI) */ /* * Map the legacy ISA devices into the IOAPIC data; We'll override these * later with data from the ACPI Interrupt Source Override table. @@ -425,8 +402,8 @@ iosapic_init (unsigned long addr) * here, so that this works on BigSur but will go ask Intel. --wfd 2000-Jan-19 * */ - for (i =0 ; i < IA64_MIN_VECTORED_IRQ; i++) { - irq = map_legacy_irq(i); + for (i =0 ; i < 16; i++) { + irq = isa_irq_to_vector(i); iosapic_pin(irq) = i; iosapic_bus(irq) = BUS_ISA; iosapic_busdata(irq) = 0; @@ -445,7 +422,9 @@ iosapic_init (unsigned long addr) ia64_boot_param.pci_vectors = (__u64) __va(ia64_boot_param.pci_vectors); vectors = (struct pci_vector_struct *) ia64_boot_param.pci_vectors; for (i = 0; i < ia64_boot_param.num_pci_vectors; i++) { - irq = map_legacy_irq(vectors[i].irq); + irq = vectors[i].irq; + if (irq < 16) + irq = isa_irq_to_vector(irq); iosapic_bustype(irq) = BUS_PCI; iosapic_pin(irq) = irq - iosapic_baseirq(irq); @@ -469,34 +448,19 @@ iosapic_init (unsigned long addr) #endif /* !CONFIG_IA64_IRQ_ACPI */ } -static void -iosapic_startup_irq (unsigned int irq) -{ - int pin; - - if (irq == TIMER_IRQ) - return; - pin = iosapic_pin(irq); - if (pin < 0) - /* happens during irq auto probing... */ - return; - set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), - iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq); - enable_pin(pin, iosapic_addr(irq)); -} - struct hw_interrupt_type irq_type_iosapic = { - "IOSAPIC", - iosapic_init, - iosapic_startup_irq, - iosapic_shutdown_irq, - iosapic_handle_irq, - iosapic_enable_irq, - iosapic_disable_irq + typename: "IOSAPIC", + startup: iosapic_startup_irq, + shutdown: iosapic_shutdown_irq, + enable: iosapic_enable_irq, + disable: iosapic_disable_irq, + ack: iosapic_ack_irq, + end: iosapic_end_irq, + set_affinity: iosapic_set_affinity }; void -dig_irq_init (struct irq_desc desc[NR_IRQS]) +dig_irq_init (void) { int i; @@ -505,10 +469,20 @@ dig_irq_init (struct irq_desc desc[NR_IRQS]) * claimed by someone else already (e.g., timer or IPI are * handled internally). */ +#if 0 for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) { - if (irq_desc[i].handler == &irq_type_default) + if (irq_desc[i].handler == &no_irq_type) irq_desc[i].handler = &irq_type_iosapic; } +#else + for (i = 0; i <= IA64_MAX_VECTORED_IRQ; ++i) { + if (irq_desc[i].handler == &no_irq_type) + irq_desc[i].handler = &irq_type_iosapic; + } +#endif +#ifndef CONFIG_IA64_DIG + iosapic_init(IO_SAPIC_DEFAULT_ADDR); +#endif } void diff --git a/arch/ia64/hp/hpsim_irq.c b/arch/ia64/hp/hpsim_irq.c index 72b36d6d6..00f4d1a51 100644 --- a/arch/ia64/hp/hpsim_irq.c +++ b/arch/ia64/hp/hpsim_irq.c @@ -1,83 +1,42 @@ /* * Platform dependent support for HP simulator. * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> - * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com> + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/kdev_t.h> -#include <linux/console.h> - -#include <asm/delay.h> -#include <asm/irq.h> -#include <asm/pal.h> -#include <asm/machvec.h> -#include <asm/pgtable.h> -#include <asm/sal.h> +#include <linux/init.h> +#include <linux/irq.h> -static int -irq_hp_sim_handle_irq (unsigned int irq, struct pt_regs *regs) +static unsigned int +hpsim_irq_startup (unsigned int irq) { - struct irqaction *action = 0; - struct irq_desc *id = irq_desc + irq; - unsigned int status; - int retval; - - spin_lock(&irq_controller_lock); - { - status = id->status; - if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) { - action = id->action; - status |= IRQ_INPROGRESS; - } - id->status = status & ~(IRQ_REPLAY | IRQ_WAITING); - } - spin_unlock(&irq_controller_lock); - - if (!action) { - if (!(id->status & IRQ_AUTODETECT)) - printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq); - return 0; - } - - retval = invoke_irq_handlers(irq, regs, action); - - spin_lock(&irq_controller_lock); - { - id->status &= ~IRQ_INPROGRESS; - } - spin_unlock(&irq_controller_lock); - - return retval; + return 0; } static void -irq_hp_sim_noop (unsigned int irq) +hpsim_irq_noop (unsigned int irq) { } static struct hw_interrupt_type irq_type_hp_sim = { - "hp_sim", - (void (*)(unsigned long)) irq_hp_sim_noop, /* init */ - irq_hp_sim_noop, /* startup */ - irq_hp_sim_noop, /* shutdown */ - irq_hp_sim_handle_irq, /* handle */ - irq_hp_sim_noop, /* enable */ - irq_hp_sim_noop, /* disable */ + typename: "hpsim", + startup: hpsim_irq_startup, + shutdown: hpsim_irq_noop, + enable: hpsim_irq_noop, + disable: hpsim_irq_noop, + ack: hpsim_irq_noop, + end: hpsim_irq_noop, + set_affinity: (void (*)(unsigned int, unsigned long)) hpsim_irq_noop, }; -void -hpsim_irq_init (struct irq_desc desc[NR_IRQS]) +void __init +hpsim_irq_init (void) { int i; for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) { - irq_desc[i].handler = &irq_type_hp_sim; + if (irq_desc[i].handler == &no_irq_type) + irq_desc[i].handler = &irq_type_hp_sim; } } diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index af51038e5..a99983681 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -50,13 +50,13 @@ put_shared_page(struct task_struct * tsk, struct page *page, unsigned long addre pmd = pmd_alloc(pgd, address); if (!pmd) { __free_page(page); - oom(tsk); + force_sig(SIGKILL, tsk); return 0; } pte = pte_alloc(pmd, address); if (!pte) { __free_page(page); - oom(tsk); + force_sig(SIGKILL, tsk); return 0; } if (!pte_none(*pte)) { diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 7cb47da72..7a2fcd214 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -15,7 +15,7 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.o -O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_default.o irq_internal.o ivt.o \ +O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_internal.o ivt.o \ pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o signal.o \ sys_ia64.o traps.o time.o unaligned.o unwind.o #O_OBJS := fpreg.o diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index e289efab6..078d908c8 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -11,6 +11,7 @@ #include <linux/config.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> @@ -22,7 +23,6 @@ #include <asm/efi.h> #include <asm/io.h> #include <asm/iosapic.h> -#include <asm/irq.h> #undef ACPI_DEBUG /* Guess what this does? */ @@ -83,8 +83,8 @@ acpi_iosapic(char *p) */ #ifdef CONFIG_IA64_DIG acpi_entry_iosapic_t *iosapic = (acpi_entry_iosapic_t *) p; - unsigned int ver; - int l, v, pins; + unsigned int ver, v; + int l, pins; ver = iosapic_version(iosapic->address); pins = (ver >> 16) & 0xff; @@ -94,9 +94,11 @@ acpi_iosapic(char *p) iosapic->irq_base, iosapic->irq_base + pins); for (l = 0; l < pins; l++) { - v = map_legacy_irq(iosapic->irq_base + l); + v = iosapic->irq_base + l; + if (v < 16) + v = isa_irq_to_vector(v); if (v > IA64_MAX_VECTORED_IRQ) { - printk(" !!! IRQ %d > 255\n", v); + printk(" !!! bad IOSAPIC interrupt vector: %u\n", v); continue; } /* XXX Check for IOSAPIC collisions */ @@ -115,7 +117,7 @@ static void __init acpi_legacy_irq(char *p) { /* - * This is not good. ACPI is not necessarily limited to CONFIG_IA64_SV, yet + * This is not good. ACPI is not necessarily limited to CONFIG_IA64_DIG, yet * ACPI does not necessarily imply IOSAPIC either. Perhaps there should be * a means for platform_setup() to register ACPI handlers? */ @@ -124,7 +126,7 @@ acpi_legacy_irq(char *p) unsigned char vector; int i; - vector = map_legacy_irq(legacy->isa_irq); + vector = isa_irq_to_vector(legacy->isa_irq); /* * Clobber any old pin mapping. It may be that it gets replaced later on diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 6e0d09ea7..fc2d50558 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -227,8 +227,8 @@ efi_init (void) panic("Woah! Can't find EFI system table.\n"); if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) panic("Woah! EFI system table signature incorrect\n"); - if (efi.systab->hdr.revision != EFI_SYSTEM_TABLE_REVISION) - printk("Warning: EFI system table version mismatch: " + if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0) + printk("Warning: EFI system table major version mismatch: " "got %d.%02d, expected %d.%02d\n", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff); diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 47b972cb4..eb575a39c 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -738,7 +738,7 @@ handle_syscall_error: st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit br.cond.sptk.many ia64_leave_kernel - .endp __ret_from_syscall + .endp handle_syscall_error #ifdef CONFIG_SMP /* @@ -767,7 +767,9 @@ invoke_schedule_tail: invoke_do_softirq: alloc loc0=ar.pfs,8,2,0,0 mov loc1=rp +(pEOI) mov cr.eoi=r0 ;; +(pEOI) cmp.ne pEOI,p0=r0,r0 br.call.sptk.few rp=do_softirq .ret9: mov ar.pfs=loc0 diff --git a/arch/ia64/kernel/fw-emu.c b/arch/ia64/kernel/fw-emu.c index 212ff299c..23ded0730 100644 --- a/arch/ia64/kernel/fw-emu.c +++ b/arch/ia64/kernel/fw-emu.c @@ -139,6 +139,24 @@ pal_emulator_static: movl r9 =0x100000064 /* proc_ratio (1/100) */ movl r10=0x100000100 /* bus_ratio<<32 (1/256) */ movl r11=0x100000064 /* itc_ratio<<32 (1/100) */ + ;; +1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */ +(p7) br.cond.sptk.few 1f + mov r9=ar.lc + movl r8=524288 /* flush 512k million cache lines (16MB) */ + ;; + mov ar.lc=r8 + movl r8=0xe000000000000000 + ;; +.loop: fc r8 + add r8=32,r8 + br.cloop.sptk.few .loop + sync.i + ;; + srlz.i + ;; + mov ar.lc=r9 + mov r8=r0 1: br.cond.sptk.few rp .endp pal_emulator_static\n"); diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index 65de8e589..a710870c0 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S @@ -82,7 +82,7 @@ ia64_sigtramp: br.call.sptk.many rp=invoke_sighandler .ret0: mov r15=__NR_rt_sigreturn break __BREAK_SYSCALL - .endp ia64_sigramp + .endp ia64_sigtramp .proc invoke_sighandler invoke_sighandler: @@ -167,7 +167,7 @@ back_from_restore_rbs: br.ret.sptk.few b6 cont: mov ar.pfs=r8 // ar.pfs = CFM0 br.ret.sptk.few rp // re-establish CFM0 - .endp invoke_signal_handler + .endp invoke_sighandler .proc setup_rbs setup_rbs: diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 6059e41c6..0ddfe3f05 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -1,105 +1,146 @@ /* - * linux/arch/ia64/kernel/irq.c + * linux/arch/ia64/kernel/irq.c * - * Copyright (C) 1998-2000 Hewlett-Packard Co - * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com> - * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * - * 6/10/99: Updated to bring in sync with x86 version to facilitate - * support for SMP and different interrupt controllers. + * This file contains the code used by various IRQ handling routines: + * asking for different IRQ's should be done through these routines + * instead of just grabbing them. Thus setups with different IRQ numbers + * shouldn't result in any weird surprises, and installing new handlers + * should be easier. */ -#include <linux/config.h> +/* + * (mostly architecture independent, will move to kernel/irq.c in 2.5.) + * + * IRQs are in fact implemented a bit like signal handlers for the kernel. + * Naturally it's not a 1:1 relation, but there are similarities. + */ -#include <linux/sched.h> +#include <linux/config.h> +#include <linux/ptrace.h> #include <linux/errno.h> -#include <linux/init.h> -#include <linux/interrupt.h> +#include <linux/signal.h> +#include <linux/sched.h> #include <linux/ioport.h> -#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <linux/timex.h> #include <linux/malloc.h> -#include <linux/ptrace.h> -#include <linux/random.h> /* for rand_initialize_irq() */ -#include <linux/signal.h> -#include <linux/smp.h> +#include <linux/random.h> #include <linux/smp_lock.h> -#include <linux/threads.h> - -#ifdef CONFIG_KDB -# include <linux/kdb.h> -#endif +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/irq.h> +#include <linux/proc_fs.h> +#include <asm/io.h> +#include <asm/smp.h> +#include <asm/system.h> #include <asm/bitops.h> +#include <asm/uaccess.h> +#include <asm/pgalloc.h> #include <asm/delay.h> -#include <asm/io.h> #include <asm/irq.h> -#include <asm/machvec.h> -#include <asm/pgtable.h> -#include <asm/system.h> -/* This is used to detect bad usage of probe_irq_on()/probe_irq_off(). */ -#define PROBE_IRQ_COOKIE 0xfeedC0FFEE -struct irq_desc irq_desc[NR_IRQS]; /* - * Micro-access to controllers is serialized over the whole - * system. We never hold this lock when we call the actual - * IRQ handler. + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. */ -spinlock_t irq_controller_lock; -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC -spinlock_t ivr_read_lock; -#endif +irq_cpustat_t irq_stat [NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; /* - * used in irq_enter()/irq_exit() + * Controller mappings for all interrupt sources: */ -unsigned int local_irq_count[NR_CPUS]; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = + { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; -static struct irqaction timer_action = { NULL, 0, 0, NULL, NULL, NULL}; +static void register_irq_proc (unsigned int irq); -#ifdef CONFIG_SMP -static struct irqaction ipi_action = { NULL, 0, 0, NULL, NULL, NULL}; -#endif +/* + * Special irq handlers. + */ + +void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } /* - * Legacy IRQ to IA-64 vector translation table. Any vector not in - * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30) + * Generic no controller code */ -__u8 irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = { - /* 8259 IRQ translation, first 16 entries */ - TIMER_IRQ, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41, -}; +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) +{ /* - * Reverse of the above table. + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves, it doesnt deserve + * a generic callback i think. */ -static __u8 vector_to_legacy_map[256]; +#if CONFIG_X86 + printk("unexpected IRQ trap at vector %02x\n", irq); +#ifdef CONFIG_X86_LOCAL_APIC + /* + * Currently unexpected vectors happen only on SMP and APIC. + * We _must_ ack these because every local APIC has only N + * irq slots per priority level, and a 'hanging, unacked' IRQ + * holds up an irq slot - in excessive cases (when multiple + * unexpected vectors occur) that might lock up the APIC + * completely. + */ + ack_APIC_irq(); +#endif +#endif +#if CONFIG_IA64 + printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id()); +#endif +} + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +struct hw_interrupt_type no_irq_type = { + "none", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; + +volatile unsigned long irq_err_count; /* - * used by proc fs (/proc/interrupts) + * Generic, controller-independent functions: */ -int -get_irq_list (char *buf) + +int get_irq_list(char *buf) { - int i; + int i, j; struct irqaction * action; char *p = buf; -#ifdef CONFIG_SMP p += sprintf(p, " "); - for (i = 0; i < smp_num_cpus; i++) - p += sprintf(p, "CPU%d ", i); + for (j=0; j<smp_num_cpus; j++) + p += sprintf(p, "CPU%d ",j); *p++ = '\n'; -#endif - /* - * Simply scans the external vectored interrupts - */ - for (i = 0; i < NR_IRQS; i++) { + + for (i = 0 ; i < NR_IRQS ; i++) { action = irq_desc[i].action; if (!action) continue; @@ -107,356 +148,496 @@ get_irq_list (char *buf) #ifndef CONFIG_SMP p += sprintf(p, "%10u ", kstat_irqs(i)); #else - { - int j; - for (j = 0; j < smp_num_cpus; j++) - p += sprintf(p, "%10u ", - kstat.irqs[cpu_logical_map(j)][i]); - } + for (j = 0; j < smp_num_cpus; j++) + p += sprintf(p, "%10u ", + kstat.irqs[cpu_logical_map(j)][i]); #endif p += sprintf(p, " %14s", irq_desc[i].handler->typename); - p += sprintf(p, " %c%s", (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); + p += sprintf(p, " %s", action->name); - for (action = action->next; action; action = action->next) { - p += sprintf(p, ", %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', - action->name); - } + for (action=action->next; action; action = action->next) + p += sprintf(p, ", %s", action->name); *p++ = '\n'; } + p += sprintf(p, "NMI: "); + for (j = 0; j < smp_num_cpus; j++) + p += sprintf(p, "%10u ", + atomic_read(&nmi_counter(cpu_logical_map(j)))); + p += sprintf(p, "\n"); +#if CONFIG_SMP + p += sprintf(p, "LOC: "); + for (j = 0; j < smp_num_cpus; j++) + p += sprintf(p, "%10u ", + apic_timer_irqs[cpu_logical_map(j)]); + p += sprintf(p, "\n"); +#endif + p += sprintf(p, "ERR: %10lu\n", irq_err_count); return p - buf; } -int usbfix; -static int __init -usbfix_option (char *str) +/* + * Global interrupt locks for SMP. Allow interrupts to come in on any + * CPU, yet make cli/sti act globally to protect critical regions.. + */ + +#ifdef CONFIG_SMP +unsigned char global_irq_holder = NO_PROC_ID; +unsigned volatile int global_irq_lock; + +extern void show_stack(unsigned long* esp); + +static void show(char * str) { - printk("irq: enabling USB workaround\n"); - usbfix = 1; - return 1; + int i; + int cpu = smp_processor_id(); + + printk("\n%s, CPU %d:\n", str, cpu); + printk("irq: %d [",irqs_running()); + for(i=0;i < smp_num_cpus;i++) + printk(" %d",local_irq_count(i)); + printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0); + for(i=0;i < smp_num_cpus;i++) + printk(" %d",local_bh_count(i)); + + printk(" ]\nStack dumps:"); + for(i=0;i< smp_num_cpus;i++) { + unsigned long esp; + if(i==cpu) + continue; + printk("\nCPU %d:",i); + esp = init_tss[i].esp0; + if(esp==NULL) { + /* tss->esp0 is set to NULL in cpu_init(), + * it's initialized when the cpu returns to user + * space. -- manfreds + */ + printk(" <unknown> "); + continue; + } + esp &= ~(THREAD_SIZE-1); + esp += sizeof(struct task_struct); + show_stack((void*)esp); + } + printk("\nCPU %d:",cpu); + show_stack(NULL); + printk("\n"); } + +#define MAXCOUNT 100000000 -__setup("usbfix", usbfix_option); +/* + * I had a lockup scenario where a tight loop doing + * spin_unlock()/spin_lock() on CPU#1 was racing with + * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but + * apparently the spin_unlock() information did not make it + * through to CPU#0 ... nasty, is this by design, do we have to limit + * 'memory update oscillation frequency' artificially like here? + * + * Such 'high frequency update' races can be avoided by careful design, but + * some of our major constructs like spinlocks use similar techniques, + * it would be nice to clarify this issue. Set this define to 0 if you + * want to check whether your system freezes. I suspect the delay done + * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but + * i thought that such things are guaranteed by design, since we use + * the 'LOCK' prefix. + */ +#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0 +#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND +# define SYNC_OTHER_CORES(x) udelay(x+1) +#else /* - * That's where the IVT branches when we get an external - * interrupt. This branches to the correct hardware IRQ handler via - * function ptr. + * We have to allow irqs to arrive between __sti and __cli */ -void -ia64_handle_irq (unsigned long irq, struct pt_regs *regs) +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +#endif + +static inline void wait_on_irq(int cpu) { - unsigned long bsp, sp, saved_tpr; - -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC -# ifndef CONFIG_SMP - static unsigned int max_prio = 0; -# endif - unsigned int prev_prio; - unsigned long eoi_ptr; - -# ifdef CONFIG_USB - extern void reenable_usb (void); - extern void disable_usb (void); - - if (usbfix) - disable_usb(); -# endif - /* - * Stop IPIs by getting the ivr_read_lock - */ - spin_lock(&ivr_read_lock); + int count = MAXCOUNT; + + for (;;) { + + /* + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. + */ + if (!irqs_running()) + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) + break; + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + clear_bit(0,&global_irq_lock); + + for (;;) { + if (!--count) { + show("wait_on_irq"); + count = ~0; + } + __sti(); + SYNC_OTHER_CORES(cpu); + __cli(); + if (irqs_running()) + continue; + if (global_irq_lock) + continue; + if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) + continue; + if (!test_and_set_bit(0,&global_irq_lock)) + break; + } + } +} - /* - * Disable PCI writes - */ - outl(0x80ff81c0, 0xcf8); - outl(0x73002188, 0xcfc); - eoi_ptr = inl(0xcfc); +/* + * This is called when we want to synchronize with + * interrupts. We may for example tell a device to + * stop sending interrupts: but to make sure there + * are no interrupts that are executing on another + * CPU we need to call this function. + */ +void synchronize_irq(void) +{ + if (irqs_running()) { + /* Stupid approach */ + cli(); + sti(); + } +} - irq = ia64_get_ivr(); +static inline void get_irqlock(int cpu) +{ + if (test_and_set_bit(0,&global_irq_lock)) { + /* do we already hold the lock? */ + if ((unsigned char) cpu == global_irq_holder) + return; + /* Uhhuh.. Somebody else got it. Wait.. */ + do { + do { + } while (test_bit(0,&global_irq_lock)); + } while (test_and_set_bit(0,&global_irq_lock)); + } + /* + * We also to make sure that nobody else is running + * in an interrupt context. + */ + wait_on_irq(cpu); /* - * Enable PCI writes + * Ok, finally.. */ - outl(0x73182188, 0xcfc); - - spin_unlock(&ivr_read_lock); + global_irq_holder = cpu; +} -# ifdef CONFIG_USB - if (usbfix) - reenable_usb(); -# endif +#define EFLAGS_IF_SHIFT 9 -# ifndef CONFIG_SMP - prev_prio = max_prio; - if (irq < max_prio) { - printk ("ia64_handle_irq: got irq %lu while %u was in progress!\n", - irq, max_prio); - - } else - max_prio = irq; -# endif /* !CONFIG_SMP */ -#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ - - /* Always set TPR to limit maximum interrupt nesting depth to - * 16 (without this, it would be ~240, which could easily lead - * to kernel stack overflows. - */ - saved_tpr = ia64_get_tpr(); - ia64_srlz_d(); - ia64_set_tpr(irq); - ia64_srlz_d(); - - asm ("mov %0=ar.bsp" : "=r"(bsp)); - asm ("mov %0=sp" : "=r"(sp)); - - if ((sp - bsp) < 1024) { - static long last_time; - static unsigned char count; - - if (count > 5 && jiffies - last_time > 5*HZ) - count = 0; - if (++count < 5) { - last_time = jiffies; - printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n" - "(bsp=0x%lx, sp=%lx)\n", bsp, sp); - } -#ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -#endif +/* + * A global "cli()" while in an interrupt context + * turns into just a local cli(). Interrupts + * should use spinlocks for the (very unlikely) + * case that they ever want to protect against + * each other. + * + * If we already have local interrupts disabled, + * this will not turn a local disable into a + * global one (problems with spinlocks: this makes + * save_flags+cli+sti usable inside a spinlock). + */ +void __global_cli(void) +{ + unsigned int flags; + + __save_flags(flags); + if (flags & (1 << EFLAGS_IF_SHIFT)) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) + get_irqlock(cpu); } +} - /* - * The interrupt is now said to be in service - */ - if (irq >= NR_IRQS) { - printk("handle_irq: invalid irq=%lu\n", irq); - goto out; - } +void __global_sti(void) +{ + int cpu = smp_processor_id(); - ++kstat.irqs[smp_processor_id()][irq]; + if (!local_irq_count(cpu)) + release_irqlock(cpu); + __sti(); +} - if (irq == IA64_SPURIOUS_INT) { - printk("handle_irq: spurious interrupt\n"); - goto out; - } +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ +unsigned long __global_save_flags(void) +{ + int retval; + int local_enabled; + unsigned long flags; + int cpu = smp_processor_id(); - /* - * Handle the interrupt by calling the hardware specific handler (IOSAPIC, Internal, etc). - */ - (*irq_desc[irq].handler->handle)(irq, regs); - out: -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC - { - long pEOI; - - asm ("mov %0=0;; (p1) mov %0=1" : "=r"(pEOI)); - if (!pEOI) { - printk("Yikes: ia64_handle_irq() without pEOI!!\n"); - asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI)); -# ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -# endif - } + __save_flags(flags); + local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1; + /* default to local */ + retval = 2 + local_enabled; + + /* check for global flags if we're not in an interrupt */ + if (!local_irq_count(cpu)) { + if (local_enabled) + retval = 1; + if (global_irq_holder == cpu) + retval = 0; } + return retval; +} - local_irq_disable(); -# ifndef CONFIG_SMP - if (max_prio == irq) - max_prio = prev_prio; -# endif /* !CONFIG_SMP */ -#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ - - ia64_srlz_d(); - ia64_set_tpr(saved_tpr); - ia64_srlz_d(); +void __global_restore_flags(unsigned long flags) +{ + switch (flags) { + case 0: + __global_cli(); + break; + case 1: + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); + break; + default: + printk("global_restore_flags: %08lx (%08lx)\n", + flags, (&flags)[-1]); + } } +#endif /* - * This should really return information about whether we should do - * bottom half handling etc. Right now we end up _always_ checking the - * bottom half, which is a waste of time and is not what some drivers - * would prefer. + * This should really return information about whether + * we should do bottom half handling etc. Right now we + * end up _always_ checking the bottom half, which is a + * waste of time and is not what some drivers would + * prefer. */ -int -invoke_irq_handlers (unsigned int irq, struct pt_regs *regs, struct irqaction *action) +int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { - void (*handler)(int, void *, struct pt_regs *); - unsigned long flags, flags_union = 0; + int status; int cpu = smp_processor_id(); - unsigned int requested_irq; - void *dev_id; irq_enter(cpu, irq); - if ((action->flags & SA_INTERRUPT) == 0) + status = 1; /* Force the "do bottom halves" bit */ + + if (!(action->flags & SA_INTERRUPT)) __sti(); do { - flags = action->flags; - requested_irq = irq; - if ((flags & SA_LEGACY) != 0) - requested_irq = vector_to_legacy_map[irq]; - flags_union |= flags; - handler = action->handler; - dev_id = action->dev_id; + status |= action->flags; + action->handler(irq, action->dev_id, regs); action = action->next; - (*handler)(requested_irq, dev_id, regs); } while (action); - if ((flags_union & SA_SAMPLE_RANDOM) != 0) + if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); __cli(); irq_exit(cpu, irq); - return flags_union | 1; /* force the "do bottom halves" bit */ + + return status; } -void -disable_irq_nosync (unsigned int irq) +/* + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ +void inline disable_irq_nosync(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; unsigned long flags; - irq = map_legacy_irq(irq); - - spin_lock_irqsave(&irq_controller_lock, flags); - if (irq_desc[irq].depth++ > 0) { - irq_desc[irq].status &= ~IRQ_ENABLED; - irq_desc[irq].handler->disable(irq); + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); } - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&desc->lock, flags); } /* * Synchronous version of the above, making sure the IRQ is * no longer running on any other IRQ.. */ -void -disable_irq (unsigned int irq) +void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - irq = map_legacy_irq(irq); - - if (!local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { do { barrier(); - } while ((irq_desc[irq].status & IRQ_INPROGRESS) != 0); + } while (irq_desc[irq].status & IRQ_INPROGRESS); } } -void -enable_irq (unsigned int irq) +void enable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; unsigned long flags; - irq = map_legacy_irq(irq); - - spin_lock_irqsave(&irq_controller_lock, flags); - switch (irq_desc[irq].depth) { - case 1: - irq_desc[irq].status |= IRQ_ENABLED; - (*irq_desc[irq].handler->enable)(irq); - /* fall through */ - default: - --irq_desc[irq].depth; + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); + /* fall-through */ + } + default: + desc->depth--; break; - - case 0: - printk("enable_irq: unbalanced from %p\n", __builtin_return_address(0)); + case 0: + printk("enable_irq() unbalanced from %p\n", + __builtin_return_address(0)); } - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&desc->lock, flags); } /* - * This function encapsulates the initialization that needs to be - * performed under the protection of lock irq_controller_lock. The - * lock must have been acquired by the time this is called. + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). */ -static inline int -setup_irq (unsigned int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; +unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs) +{ + /* + * We ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * 0 return value means that this irq is already being + * handled by some other CPU. (or is disabled) + */ + int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; + unsigned int status; - p = &irq_desc[irq].action; - old = *p; - if (old) { - if (!(old->flags & new->flags & SA_SHIRQ)) { - return -EBUSY; - } - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; + kstat.irqs[cpu][irq]++; + spin_lock(&desc->lock); + desc->handler->ack(irq); + /* + REPLAY is when Linux resends an IRQ that was dropped earlier + WAITING is used by probe to mark irqs that are being tested + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + action = desc->action; + status &= ~IRQ_PENDING; /* we commit to handling */ + status |= IRQ_INPROGRESS; /* we are handling it */ } - *p = new; + desc->status = status; - /* when sharing do not unmask */ - if (!shared) { - irq_desc[irq].depth = 0; - irq_desc[irq].status |= IRQ_ENABLED; - (*irq_desc[irq].handler->startup)(irq); + /* + * If there is no IRQ handler or it was disabled, exit early. + Since we set PENDING, if another processor is handling + a different instance of this same irq, the other processor + will take care of it. + */ + if (!action) +{ + desc->status = status & ~IRQ_INPROGRESS; + goto out; +} + + /* + * Edge triggered interrupts need to remember + * pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in do_IRQ + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + spin_unlock(&desc->lock); + handle_IRQ_event(irq, regs, action); + spin_lock(&desc->lock); + + if (!(desc->status & IRQ_PENDING)) + break; + desc->status &= ~IRQ_PENDING; } - return 0; + desc->status &= ~IRQ_INPROGRESS; +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); + +#if 0 + /* + * let kernel exit path take care of this; we want to do the + * CPU EOI before doing softirq() so a new interrupt can come + * through + */ + if (softirq_state[cpu].active & softirq_state[cpu].mask) + do_softirq(); +#endif + return 1; } -int -request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) { - int retval, need_kfree = 0; - struct irqaction *action; - unsigned long flags; - unsigned int irq; + int retval; + struct irqaction * action; -#ifdef IA64_DEBUG - printk("request_irq(0x%x) called\n", requested_irq); -#endif +#if 1 /* * Sanity-check: shared interrupts should REALLY pass in * a real dev-ID, otherwise we'll have trouble later trying * to figure out which interrupt is which (messes up the * interrupt freeing logic etc). */ - if ((irqflags & SA_SHIRQ) && !dev_id) - printk("Bad boy: %s (at %p) called us without a dev_id!\n", - devname, current_text_addr()); - - irq = map_legacy_irq(requested_irq); - if (irq != requested_irq) - irqflags |= SA_LEGACY; + if (irqflags & SA_SHIRQ) { + if (!dev_id) + printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); + } +#endif if (irq >= NR_IRQS) return -EINVAL; - if (!handler) return -EINVAL; - /* - * The timer_action and ipi_action cannot be allocated - * dynamically because its initialization happens really early - * on in init/main.c at this point the memory allocator has - * not yet been initialized. So we use a statically reserved - * buffer for it. In some sense that's no big deal because we - * need one no matter what. - */ - if (irq == TIMER_IRQ) - action = &timer_action; -#ifdef CONFIG_SMP - else if (irq == IPI_IRQ) - action = &ipi_action; -#endif - else { - action = kmalloc(sizeof(struct irqaction), GFP_KERNEL); - need_kfree = 1; - } - + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; @@ -467,208 +648,412 @@ request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_ action->next = NULL; action->dev_id = dev_id; - if ((irqflags & SA_SAMPLE_RANDOM) != 0) - rand_initialize_irq(irq); - - spin_lock_irqsave(&irq_controller_lock, flags); retval = setup_irq(irq, action); - spin_unlock_irqrestore(&irq_controller_lock, flags); - - if (need_kfree && retval) + if (retval) kfree(action); - return retval; } -void -free_irq (unsigned int irq, void *dev_id) +void free_irq(unsigned int irq, void *dev_id) { - struct irqaction *action, **p; + irq_desc_t *desc; + struct irqaction **p; unsigned long flags; - /* - * some sanity checks first - */ - if (irq >= NR_IRQS) { - printk("Trying to free IRQ%d\n",irq); + if (irq >= NR_IRQS) return; - } - irq = map_legacy_irq(irq); - - /* - * Find the corresponding irqaction - */ - spin_lock_irqsave(&irq_controller_lock, flags); - for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *p = action->next; - if (!irq_desc[irq].action) { - irq_desc[irq].status &= ~IRQ_ENABLED; - (*irq_desc[irq].handler->shutdown)(irq); - } - - spin_unlock_irqrestore(&irq_controller_lock, flags); + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); #ifdef CONFIG_SMP - /* Wait to make sure it's not being used on another CPU */ - while (irq_desc[irq].status & IRQ_INPROGRESS) - barrier(); + /* Wait to make sure it's not being used on another CPU */ + while (desc->status & IRQ_INPROGRESS) + barrier(); #endif - - if (action != &timer_action -#ifdef CONFIG_SMP - && action != &ipi_action -#endif - ) kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); return; } - printk("Trying to free free IRQ%d\n", irq); } /* - * IRQ autodetection code. Note that the return value of - * probe_irq_on() is no longer being used (it's role has been replaced - * by the IRQ_AUTODETECT flag). + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. */ -unsigned long -probe_irq_on (void) +unsigned long probe_irq_on(void) { - struct irq_desc *id; + unsigned int i; + irq_desc_t *desc; + unsigned long val; unsigned long delay; -#ifdef IA64_DEBUG - printk("probe_irq_on() called\n"); -#endif + /* + * something may have generated an irq long ago and we want to + * flush such a longstanding irq before considering it as spurious. + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; - spin_lock_irq(&irq_controller_lock); - for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) { - if (!id->action) { - id->status |= IRQ_AUTODETECT | IRQ_WAITING; - (*id->handler->startup)(id - irq_desc); - } + spin_lock_irq(&desc->lock); + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); - /* wait for spurious interrupts to trigger: */ + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ synchronize_irq(); - for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ - synchronize_irq(); - - /* filter out obviously spurious interrupts: */ - spin_lock_irq(&irq_controller_lock); - for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) { - unsigned int status = id->status; + /* + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; + } + spin_unlock_irq(&desc->lock); + } - if (!(status & IRQ_AUTODETECT)) - continue; + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ synchronize_irq(); - if (!(status & IRQ_WAITING)) { - id->status = status & ~IRQ_AUTODETECT; - (*id->handler->shutdown)(id - irq_desc); + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; } + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); - return PROBE_IRQ_COOKIE; /* return meaningless return value */ + + return val; } -int -probe_irq_off (unsigned long cookie) +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ +unsigned int probe_irq_mask(unsigned long val) { - int irq_found, nr_irqs; - struct irq_desc *id; + int i; + unsigned int mask; -#ifdef IA64_DEBUG - printk("probe_irq_off(cookie=0x%lx) -> ", cookie); -#endif + mask = 0; + for (i = 0; i < 16; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; - if (cookie != PROBE_IRQ_COOKIE) - printk("bad irq probe from %p\n", __builtin_return_address(0)); + spin_lock_irq(&desc->lock); + status = desc->status; - nr_irqs = 0; - irq_found = 0; - spin_lock_irq(&irq_controller_lock); - for (id = irq_desc + IA64_MIN_VECTORED_IRQ; id < irq_desc + NR_IRQS; ++id) { - unsigned int status = id->status; + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) + mask |= 1 << i; - if (!(status & IRQ_AUTODETECT)) - continue; + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + + return mask & val; +} - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = (id - irq_desc); - ++nr_irqs; +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source) + */ +int probe_irq_off(unsigned long val) +{ + int i, irq_found, nr_irqs; + + nr_irqs = 0; + irq_found = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); } - id->status = status & ~IRQ_AUTODETECT; - (*id->handler->shutdown)(id - irq_desc); + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); if (nr_irqs > 1) irq_found = -irq_found; - -#ifdef IA64_DEBUG - printk("%d\n", irq_found); -#endif return irq_found; } -#ifdef CONFIG_SMP - -void __init -init_IRQ_SMP (void) +/* this was setup_x86_irq but it seems pretty generic */ +int setup_irq(unsigned int irq, struct irqaction * new) { - if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL)) - panic("Could not allocate IPI Interrupt Handler!"); + int shared = 0; + unsigned long flags; + struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } + + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= ~IRQ_DISABLED; + desc->handler->startup(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + register_irq_proc(irq); + return 0; } -#endif +static struct proc_dir_entry * root_irq_dir; +static struct proc_dir_entry * irq_dir [NR_IRQS]; +static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; + +static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; -void __init -init_IRQ (void) +#define HEX_DIGITS 8 + +static int irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) { + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", irq_affinity[(long)data]); +} + +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) +{ + unsigned char hexnum [HEX_DIGITS]; + unsigned long value; int i; - for (i = 0; i < IA64_MIN_VECTORED_IRQ; ++i) - vector_to_legacy_map[irq_to_vector_map[i]] = i; + if (!count) + return -EINVAL; + if (count > HEX_DIGITS) + count = HEX_DIGITS; + if (copy_from_user(hexnum, buffer, count)) + return -EFAULT; + + /* + * Parse the first 8 characters as a hex string, any non-hex char + * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. + */ + value = 0; + + for (i = 0; i < count; i++) { + unsigned int c = hexnum[i]; - for (i = 0; i < NR_IRQS; ++i) { - irq_desc[i].handler = &irq_type_default; + switch (c) { + case '0' ... '9': c -= '0'; break; + case 'a' ... 'f': c -= 'a'-10; break; + case 'A' ... 'F': c -= 'A'-10; break; + default: + goto out; + } + value = (value << 4) | c; } +out: + *ret = value; + return 0; +} - irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; -#ifdef CONFIG_SMP - /* - * Configure the IPI vector and handler +static int irq_affinity_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int irq = (long) data, full_count = count, err; + unsigned long new_value; + + if (!irq_desc[irq].handler->set_affinity) + return -EIO; + + err = parse_hex_value(buffer, count, &new_value); + +#if CONFIG_SMP + /* + * Do not allow disabling IRQs completely - it's a too easy + * way to make the system unusable accidentally :-) At least + * one online CPU still has to be targeted. */ - irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal; - init_IRQ_SMP(); + if (!(new_value & cpu_online_map)) + return -EINVAL; #endif - ia64_set_pmv(1 << 16); - ia64_set_cmcv(CMC_IRQ); /* XXX fix me */ + irq_affinity[irq] = new_value; + irq_desc[irq].handler->set_affinity(irq, new_value); - platform_irq_init(irq_desc); + return full_count; +} - /* clear TPR to enable all interrupt classes: */ - ia64_set_tpr(0); +static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned long *mask = (unsigned long *) data; + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", *mask); } -/* TBD: - * Certain IA64 platforms can have inter-processor interrupt support. - * This interface is supposed to default to the IA64 IPI block-based - * mechanism if the platform doesn't provide a separate mechanism - * for IPIs. - * Choices : (1) Extend hw_interrupt_type interfaces - * (2) Use machine vector mechanism - * For now defining the following interface as a place holder. - */ -void -ipi_send (int cpu, int vector, int delivery_mode) +static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) { + unsigned long *mask = (unsigned long *) data, full_count = count, err; + unsigned long new_value; + + err = parse_hex_value(buffer, count, &new_value); + if (err) + return err; + + *mask = new_value; + return full_count; } + +#define MAX_NAMELEN 10 + +static void register_irq_proc (unsigned int irq) +{ + struct proc_dir_entry *entry; + char name [MAX_NAMELEN]; + + if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type)) + return; + + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + irq_dir[irq] = proc_mkdir(name, root_irq_dir); + + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + + smp_affinity_entry[irq] = entry; +} + +unsigned long prof_cpu_mask = -1; + +void init_irq_proc (void) +{ + struct proc_dir_entry *entry; + int i; + + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", 0); + + /* create /proc/irq/prof_cpu_mask */ + entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + + entry->nlink = 1; + entry->data = (void *)&prof_cpu_mask; + entry->read_proc = prof_cpu_mask_read_proc; + entry->write_proc = prof_cpu_mask_write_proc; + + /* + * Create entries for all existing IRQs. + */ + for (i = 0; i < NR_IRQS; i++) { + if (irq_desc[i].handler == &no_irq_type) + continue; + register_irq_proc(i); + } +} + diff --git a/arch/ia64/kernel/irq_default.c b/arch/ia64/kernel/irq_default.c deleted file mode 100644 index bf8c62642..000000000 --- a/arch/ia64/kernel/irq_default.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <linux/kernel.h> -#include <linux/sched.h> - -#include <asm/irq.h> -#include <asm/processor.h> -#include <asm/ptrace.h> - - -static int -irq_default_handle_irq (unsigned int irq, struct pt_regs *regs) -{ - printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id()); - return 0; /* don't call do_bottom_half() for spurious interrupts */ -} - -static void -irq_default_noop (unsigned int irq) -{ - /* nuthing to do... */ -} - -struct hw_interrupt_type irq_type_default = { - "default", - (void (*)(unsigned long)) irq_default_noop, /* init */ - irq_default_noop, /* startup */ - irq_default_noop, /* shutdown */ - irq_default_handle_irq, /* handle */ - irq_default_noop, /* enable */ - irq_default_noop /* disable */ -}; diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c new file mode 100644 index 000000000..a2c493ba5 --- /dev/null +++ b/arch/ia64/kernel/irq_ia64.c @@ -0,0 +1,247 @@ +/* + * linux/arch/ia64/kernel/irq.c + * + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com> + * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com> + * + * 6/10/99: Updated to bring in sync with x86 version to facilitate + * support for SMP and different interrupt controllers. + */ + +#include <linux/config.h> + +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/kernel_stat.h> +#include <linux/malloc.h> +#include <linux/ptrace.h> +#include <linux/random.h> /* for rand_initialize_irq() */ +#include <linux/signal.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/threads.h> + +#ifdef CONFIG_KDB +# include <linux/kdb.h> +#endif + +#include <asm/bitops.h> +#include <asm/delay.h> +#include <asm/io.h> +#include <asm/hw_irq.h> +#include <asm/machvec.h> +#include <asm/pgtable.h> +#include <asm/system.h> + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC +spinlock_t ivr_read_lock; +#endif + +/* + * Legacy IRQ to IA-64 vector translation table. Any vector not in + * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30) + */ +__u8 isa_irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = { + /* 8259 IRQ translation, first 16 entries */ + 0x60, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41 +}; + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + +int usbfix; + +static int __init +usbfix_option (char *str) +{ + printk("irq: enabling USB workaround\n"); + usbfix = 1; + return 1; +} + +__setup("usbfix", usbfix_option); + +#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ + +/* + * That's where the IVT branches when we get an external + * interrupt. This branches to the correct hardware IRQ handler via + * function ptr. + */ +void +ia64_handle_irq (unsigned long vector, struct pt_regs *regs) +{ + unsigned long bsp, sp, saved_tpr; + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC +# ifndef CONFIG_SMP + static unsigned int max_prio = 0; +# endif + unsigned int prev_prio; + unsigned long eoi_ptr; + +# ifdef CONFIG_USB + extern void reenable_usb (void); + extern void disable_usb (void); + + if (usbfix) + disable_usb(); +# endif + /* + * Stop IPIs by getting the ivr_read_lock + */ + spin_lock(&ivr_read_lock); + + /* + * Disable PCI writes + */ + outl(0x80ff81c0, 0xcf8); + outl(0x73002188, 0xcfc); + eoi_ptr = inl(0xcfc); + + vector = ia64_get_ivr(); + + /* + * Enable PCI writes + */ + outl(0x73182188, 0xcfc); + + spin_unlock(&ivr_read_lock); + +# ifdef CONFIG_USB + if (usbfix) + reenable_usb(); +# endif + +# ifndef CONFIG_SMP + prev_prio = max_prio; + if (vector < max_prio) { + printk ("ia64_handle_irq: got vector %lu while %u was in progress!\n", + vector, max_prio); + + } else + max_prio = vector; +# endif /* !CONFIG_SMP */ +#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ + + /* + * Always set TPR to limit maximum interrupt nesting depth to + * 16 (without this, it would be ~240, which could easily lead + * to kernel stack overflows. + */ + saved_tpr = ia64_get_tpr(); + ia64_srlz_d(); + ia64_set_tpr(vector); + ia64_srlz_d(); + + asm ("mov %0=ar.bsp" : "=r"(bsp)); + asm ("mov %0=sp" : "=r"(sp)); + + if ((sp - bsp) < 1024) { + static long last_time; + static unsigned char count; + + if (count > 5 && jiffies - last_time > 5*HZ) + count = 0; + if (++count < 5) { + last_time = jiffies; + printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n" + "(bsp=0x%lx, sp=%lx)\n", bsp, sp); + } +#ifdef CONFIG_KDB + kdb(KDB_REASON_PANIC, 0, regs); +#endif + } + + /* + * The interrupt is now said to be in service + */ + if (vector >= NR_IRQS) { + printk("handle_irq: invalid vector %lu\n", vector); + goto out; + } + + do_IRQ(vector, regs); + out: +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + { + long pEOI; + + asm ("mov %0=0;; (p1) mov %0=1" : "=r"(pEOI)); + if (!pEOI) { + printk("Yikes: ia64_handle_irq() without pEOI!!\n"); + asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI)); +# ifdef CONFIG_KDB + kdb(KDB_REASON_PANIC, 0, regs); +# endif + } + } + + local_irq_disable(); +# ifndef CONFIG_SMP + if (max_prio == vector) + max_prio = prev_prio; +# endif /* !CONFIG_SMP */ +#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ + + ia64_srlz_d(); + ia64_set_tpr(saved_tpr); + ia64_srlz_d(); +} + +#ifdef CONFIG_SMP + +void __init +init_IRQ_SMP (void) +{ + if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL)) + panic("Could not allocate IPI Interrupt Handler!"); +} + +#endif + +void __init +init_IRQ (void) +{ + /* + * Disable all local interrupts + */ + ia64_set_itv(0, 1); + ia64_set_lrr0(0, 1); + ia64_set_lrr1(0, 1); + + irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; +#ifdef CONFIG_SMP + /* + * Configure the IPI vector and handler + */ + irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal; + init_IRQ_SMP(); +#endif + + ia64_set_pmv(1 << 16); + ia64_set_cmcv(CMC_IRQ); /* XXX fix me */ + + platform_irq_init(); + + /* clear TPR to enable all interrupt classes: */ + ia64_set_tpr(0); +} + +/* TBD: + * Certain IA64 platforms can have inter-processor interrupt support. + * This interface is supposed to default to the IA64 IPI block-based + * mechanism if the platform doesn't provide a separate mechanism + * for IPIs. + * Choices : (1) Extend hw_interrupt_type interfaces + * (2) Use machine vector mechanism + * For now defining the following interface as a place holder. + */ +void +ipi_send (int cpu, int vector, int delivery_mode) +{ +} diff --git a/arch/ia64/kernel/irq_internal.c b/arch/ia64/kernel/irq_internal.c index cc59e0c72..2b768cec1 100644 --- a/arch/ia64/kernel/irq_internal.c +++ b/arch/ia64/kernel/irq_internal.c @@ -6,51 +6,16 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> */ -#include <linux/kernel.h> -#include <linux/sched.h> +#include <linux/irq.h> -#include <asm/irq.h> -#include <asm/processor.h> -#include <asm/ptrace.h> - -/* - * This is identical to IOSAPIC handle_irq. It may go away . . . - */ -static int -internal_handle_irq (unsigned int irq, struct pt_regs *regs) +static unsigned int +internal_noop_startup (unsigned int irq) { - struct irqaction *action = 0; - struct irq_desc *id = irq_desc + irq; - unsigned int status; - int retval; - - spin_lock(&irq_controller_lock); - { - status = id->status; - if ((status & IRQ_ENABLED) != 0) - action = id->action; - id->status = status & ~(IRQ_REPLAY | IRQ_WAITING); - } - spin_unlock(&irq_controller_lock); - - if (!action) { - if (!(id->status & IRQ_AUTODETECT)) - printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq); - return 0; - } - - retval = invoke_irq_handlers(irq, regs, action); - - spin_lock(&irq_controller_lock); - { - status = (id->status & ~IRQ_INPROGRESS); - id->status = status; - } - spin_unlock(&irq_controller_lock); - - return retval; + return 0; } static void @@ -60,12 +25,12 @@ internal_noop (unsigned int irq) } struct hw_interrupt_type irq_type_ia64_internal = { - "IA64-internal", - (void (*)(unsigned long)) internal_noop, /* init */ - internal_noop, /* startup */ - internal_noop, /* shutdown */ - internal_handle_irq, /* handle */ - internal_noop, /* enable */ - internal_noop /* disable */ + typename: "IA64-internal", + startup: internal_noop_startup, + shutdown: internal_noop, + enable: internal_noop, + disable: internal_noop, + ack: internal_noop, + end: internal_noop, + set_affinity: (void (*)(unsigned int, unsigned long)) internal_noop }; - diff --git a/arch/ia64/kernel/irq_lock.c b/arch/ia64/kernel/irq_lock.c index 4a2ead673..43afeac60 100644 --- a/arch/ia64/kernel/irq_lock.c +++ b/arch/ia64/kernel/irq_lock.c @@ -281,7 +281,7 @@ __global_restore_flags(unsigned long flags) __sti(); break; default: - printk("global_restore_flags: %08lx (%08lx)\n", - flags, (&flags)[-1]); + printk("global_restore_flags: %08lx (%08lx) from %p\n", + flags, (&flags)[-1], __builtin_return_address(0)); } } diff --git a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c index 4acc7f041..767cfa5ce 100644 --- a/arch/ia64/kernel/pci.c +++ b/arch/ia64/kernel/pci.c @@ -164,13 +164,6 @@ pcibios_fixup_bus(struct pci_bus *b) return; } -int -pci_assign_resource (struct pci_dev *dev, int i) -{ - printk("pci_assign_resource: not implemented!\n"); - return -ENODEV; -} - void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 274b68a73..29291e1f9 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -1,15 +1,53 @@ -#include <linux/config.h> +/* + * This file contains the code to configure and read/write the ia64 performance + * monitoring stuff. + * + * Originaly Written by Ganesh Venkitachalam, IBM Corp. + * Modifications by David Mosberger-Tang, Hewlett-Packard Co. + * Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com> + * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> + */ +#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp_lock.h> #include <asm/errno.h> -#include <asm/irq.h> +#include <asm/hw_irq.h> #include <asm/processor.h> #include <asm/system.h> #include <asm/uaccess.h> +/* Long blurb on how this works: + * We set dcr.pp, psr.pp, and the appropriate pmc control values with + * this. Notice that we go about modifying _each_ task's pt_regs to + * set cr_ipsr.pp. This will start counting when "current" does an + * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited + * across forks, we do _not_ need additional code on context + * switches. On stopping of the counters we dont need to go about + * changing every task's cr_ipsr back to where it wuz, because we can + * just set pmc[0]=1. But we do it anyways becuase we will probably + * add thread specific accounting later. + * + * The obvious problem with this is that on SMP systems, it is a bit + * of work (when someone wants to do it:-)) - it would be easier if we + * just added code to the context-switch path, but if we wanted to support + * per-thread accounting, the context-switch path might be long unless + * we introduce a flag in the task_struct. Right now, the following code + * will NOT work correctly on MP (for more than one reason:-)). + * + * The short answer is that to make this work on SMP, we would need + * to lock the run queue to ensure no context switches, send + * an IPI to each processor, and in that IPI handler, set processor regs, + * and just modify the psr bit of only the _current_ thread, since we have + * modified the psr bit correctly in the kernel stack for every process + * which is not running. Also, we need pmd arrays per-processor, and + * the READ_PMD command will need to get values off of other processors. + * IPIs are the answer, irrespective of what the question is. Might + * crash on SMP systems without the lock_kernel(). + */ + #ifdef CONFIG_PERFMON #define MAX_PERF_COUNTER 4 /* true for Itanium, at least */ @@ -22,33 +60,12 @@ struct perfmon_counter { unsigned long data; - int counter_num; + unsigned long counter_num; }; unsigned long pmds[MAX_PERF_COUNTER]; -struct task_struct *perf_owner; +struct task_struct *perf_owner=NULL; -/* - * We set dcr.pp, psr.pp, and the appropriate pmc control values with - * this. Notice that we go about modifying _each_ task's pt_regs to - * set cr_ipsr.pp. This will start counting when "current" does an - * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited - * across forks, we do _not_ need additional code on context - * switches. On stopping of the counters we dont _need_ to go about - * changing every task's cr_ipsr back to where it wuz, because we can - * just set pmc[0]=1. But we do it anyways becuase we will probably - * add thread specific accounting later. - * - * The obvious problem with this is that on SMP systems, it is a bit - * of work (when someone wants to do it) - it would be easier if we - * just added code to the context-switch path. I think we would need - * to lock the run queue to ensure no context switches, send an IPI to - * each processor, and in that IPI handler, just modify the psr bit of - * only the _current_ thread, since we have modified the psr bit - * correctly in the kernel stack for every process which is not - * running. Might crash on SMP systems without the - * lock_kernel(). Hence the lock.. - */ asmlinkage unsigned long sys_perfmonctl (int cmd1, int cmd2, void *ptr) { @@ -66,7 +83,7 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) if (!access_ok(VERIFY_READ, cptr, sizeof(struct perf_counter)*cmd2)) return -EFAULT; - if (cmd2 >= MAX_PERF_COUNTER) + if (cmd2 > MAX_PERF_COUNTER) return -EFAULT; if (perf_owner && perf_owner != current) @@ -91,15 +108,12 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) /* * This is a no can do. It obviously wouldn't * work on SMP where another process may not - * be blocked at all. - * - * Perhaps we need a global predicate in the - * leave_kernel path to control if pp should - * be on or off? + * be blocked at all. We need to put in a perfmon + * IPI to take care of MP systems. See blurb above. */ lock_kernel(); for_each_task(p) { - regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) - 1; + regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) -1 ; ia64_psr(regs)->pp = 1; } unlock_kernel(); @@ -108,12 +122,18 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) break; case READ_PMDS: - if (cmd2 >= MAX_PERF_COUNTER) + if (cmd2 > MAX_PERF_COUNTER) return -EFAULT; if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perf_counter)*cmd2)) return -EFAULT; + + /* This looks shady, but IMHO this will work fine. This is + * the sequence that I could come up with to avoid races + * with the interrupt handler. See explanation in the + * following comment. + */ + local_irq_save(flags); - /* XXX this looks wrong */ __asm__ __volatile__("rsm psr.pp\n"); dcr = ia64_get_dcr(); dcr &= ~IA64_DCR_PP; @@ -121,23 +141,23 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) local_irq_restore(flags); /* - * We cannot touch pmc[0] to stop counting here, as + * We cannot write to pmc[0] to stop counting here, as * that particular instruction might cause an overflow - * and the mask in pmc[0] might get lost. I'm not very + * and the mask in pmc[0] might get lost. I'm _not_ * sure of the hardware behavior here. So we stop * counting by psr.pp = 0. And we reset dcr.pp to * prevent an interrupt from mucking up psr.pp in the * meanwhile. Perfmon interrupts are pended, hence the - * above code should be ok if one of the above - * instructions cause overflows. Is this ok? When I - * muck with dcr, is the cli/sti needed?? + * above code should be ok if one of the above instructions + * caused overflows, i.e the interrupt should get serviced + * when we re-enabled interrupts. When I muck with dcr, + * is the irq_save/restore needed? */ - for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; i++, cnum++, cptr++) { + for (i = 0, cnum = 4;i < MAX_PERF_COUNTER; i++, cnum++, cptr++){ pmd = pmds[i] + (ia64_get_pmd(cnum) & PERF_OVFL_VAL); put_user(pmd, &cptr->data); } local_irq_save(flags); - /* XXX this looks wrong */ __asm__ __volatile__("ssm psr.pp"); dcr = ia64_get_dcr(); dcr |= IA64_DCR_PP; @@ -158,11 +178,8 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) /* * This is a no can do. It obviously wouldn't * work on SMP where another process may not - * be blocked at all. - * - * Perhaps we need a global predicate in the - * leave_kernel path to control if pp should - * be on or off? + * be blocked at all. We need to put in a perfmon + * IPI to take care of MP systems. See blurb above. */ lock_kernel(); for_each_task(p) { @@ -170,7 +187,7 @@ sys_perfmonctl (int cmd1, int cmd2, void *ptr) ia64_psr(regs)->pp = 0; } unlock_kernel(); - perf_owner = 0; + perf_owner = NULL; break; default: @@ -184,12 +201,12 @@ update_counters (void) { unsigned long mask, i, cnum, val; - mask = ia64_get_pmd(0) >> 4; + mask = ia64_get_pmc(0) >> 4; for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; cnum++, i++, mask >>= 1) { if (mask & 0x1) val = PERF_OVFL_VAL; else - /* since we got an interrupt, might as well clear every pmd. */ + /* since we got an interrupt, might as well clear every pmd. */ val = ia64_get_pmd(cnum) & PERF_OVFL_VAL; pmds[i] += val; ia64_set_pmd(cnum, 0); @@ -214,10 +231,10 @@ perfmon_init (void) } ia64_set_pmv(PERFMON_IRQ); ia64_srlz_d(); + printk("Initialized perfmon vector to %u\n",PERFMON_IRQ); } #else /* !CONFIG_PERFMON */ - asmlinkage unsigned long sys_perfmonctl (int cmd1, int cmd2, void *ptr) { diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index cc26b8760..a8c217b9a 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -99,7 +99,7 @@ cpu_idle (void *unused) (*pm_idle)(); #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC if (ia64_get_itm() < ia64_get_itc()) { - extern void ia64_reset_itm(); + extern void ia64_reset_itm (void); printk("cpu_idle: ITM in past, resetting it...\n"); ia64_reset_itm(); @@ -238,7 +238,7 @@ void ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst) { struct switch_stack *sw = ((struct switch_stack *) pt) - 1; - unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs; + unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs, addr; ar_ec = (sw->ar_pfs >> 52) & 0x3f; @@ -249,8 +249,18 @@ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst) } krbs = (unsigned long *) current + IA64_RBS_OFFSET/8; - ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 16)); - ar_bsp = (long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty); + ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); + ar_bsp = (unsigned long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty); + + /* + * Write portion of RSE backing store living on the kernel + * stack to the VM of the process. + */ + for (addr = pt->ar_bspstore; addr < ar_bsp; addr += 8) { + long val; + if (ia64_peek(pt, current, addr, &val) == 0) + access_process_vm(current, addr, &val, sizeof(val), 1); + } /* r0-r31 * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT) @@ -310,7 +320,6 @@ sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs) { int error; - lock_kernel(); filename = getname(filename); error = PTR_ERR(filename); if (IS_ERR(filename)) @@ -318,7 +327,6 @@ sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs) error = do_execve(filename, argv, envp, regs); putname(filename); out: - unlock_kernel(); return error; } diff --git a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c index 84581af2e..980fa4329 100644 --- a/arch/ia64/kernel/semaphore.c +++ b/arch/ia64/kernel/semaphore.c @@ -138,9 +138,10 @@ __down_interruptible (struct semaphore * sem) int __down_trylock (struct semaphore *sem) { + unsigned long flags; int sleepers; - spin_lock_irq(&semaphore_lock); + spin_lock_irqsave(&semaphore_lock, flags); sleepers = sem->sleepers + 1; sem->sleepers = 0; @@ -151,7 +152,7 @@ __down_trylock (struct semaphore *sem) if (!atomic_add_negative(sleepers, &sem->count)) wake_up(&sem->wait); - spin_unlock_irq(&semaphore_lock); + spin_unlock_irqrestore(&semaphore_lock, flags); return 1; } diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index f3283d535..58ddb1fb1 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -101,6 +101,7 @@ void __init setup_arch (char **cmdline_p) { unsigned long max_pfn, bootmap_start, bootmap_size; + u64 progress; /* * The secondary bootstrap loader passes us the boot @@ -167,6 +168,7 @@ setup_arch (char **cmdline_p) conswitchp = &dummy_con; # endif #endif + paging_init(); platform_setup(cmdline_p); } diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index cfcff3063..133520b84 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -10,21 +10,17 @@ */ #include <linux/config.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/time.h> #include <asm/delay.h> #include <asm/efi.h> -#include <asm/irq.h> -#include <asm/machvec.h> +#include <asm/hw_irq.h> #include <asm/ptrace.h> #include <asm/sal.h> #include <asm/system.h> -#ifdef CONFIG_KDB -# include <linux/kdb.h> -#endif - extern rwlock_t xtime_lock; extern volatile unsigned long lost_ticks; @@ -43,8 +39,12 @@ static struct { static void do_profile (unsigned long ip) { + extern unsigned long prof_cpu_mask; extern char _stext; + if (!((1UL << smp_processor_id()) & prof_cpu_mask)) + return; + if (prof_buffer && current->pid) { ip -= (unsigned long) &_stext; ip >>= prof_shift; @@ -65,7 +65,7 @@ do_profile (unsigned long ip) * update to jiffy. The xtime_lock must be at least read-locked when * calling this routine. */ -static /*inline*/ unsigned long +static inline unsigned long gettimeoffset (void) { unsigned long now = ia64_get_itc(); @@ -198,7 +198,7 @@ ia64_reset_itm (void) unsigned long flags; local_irq_save(flags); - timer_interrupt(0, 0, current); + timer_interrupt(0, 0, ia64_task_regs(current)); local_irq_restore(flags); } @@ -293,15 +293,19 @@ ia64_init_itm (void) ia64_cpu_local_tick(); } +static struct irqaction timer_irqaction = { + handler: timer_interrupt, + flags: SA_INTERRUPT, + name: "timer" +}; + void __init time_init (void) { - /* - * Request the IRQ _before_ doing anything to cause that - * interrupt to be posted. - */ - if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer", NULL)) - panic("Could not allocate timer IRQ!"); + /* we can't do request_irq() here because the kmalloc() would fail... */ + irq_desc[TIMER_IRQ].status = IRQ_DISABLED; + irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; + setup_irq(TIMER_IRQ, &timer_irqaction); efi_gettimeofday(&xtime); ia64_init_itm(); diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 1f5106036..ddb079f13 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -456,7 +456,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 32: /* fp fault */ case 33: /* fp trap */ - result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, &isr); + result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr); if (result < 0) { siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; diff --git a/arch/ia64/lib/copy_page.S b/arch/ia64/lib/copy_page.S index 0a956e5a2..7595ac83a 100644 --- a/arch/ia64/lib/copy_page.S +++ b/arch/ia64/lib/copy_page.S @@ -15,6 +15,9 @@ */ #include <asm/page.h> +#define PIPE_DEPTH 6 +#define EPI p[PIPE_DEPTH-1] + #define lcount r16 #define saved_pr r17 #define saved_lc r18 @@ -34,10 +37,10 @@ .proc copy_page copy_page: - alloc saved_pfs=ar.pfs,10,0,0,8 // we need 6 roatating (8 minimum) - // + 2 input + alloc saved_pfs=ar.pfs,3,((2*PIPE_DEPTH+7)&~7),0,((2*PIPE_DEPTH+7)&~7) - .rotr t1[4], t2[4] // our 2 pipelines with depth of 4 each + .rotr t1[PIPE_DEPTH], t2[PIPE_DEPTH] + .rotp p[PIPE_DEPTH] mov saved_lc=ar.lc // save ar.lc ahead of time mov saved_pr=pr // rotating predicates are preserved @@ -53,29 +56,30 @@ copy_page: mov pr.rot=1<<16 // pr16=1 & pr[17-63]=0 , 63 not modified mov ar.lc=lcount // set loop counter - mov ar.ec=4 // ar.ec must match pipeline depth + mov ar.ec=PIPE_DEPTH // ar.ec must match pipeline depth ;; // We need to preload the n-1 stages of the pipeline (n=depth). // We do this during the "prolog" of the loop: we execute // n-1 times the "load" bundle. Then both loads & stores are // enabled until we reach the end of the last word of the page - // on the load side. Then, we enter the epilogue (controlled by ec) - // where we just do the stores and no loads n-1 times : drain the pipe. + // on the load side. Then, we enter the epilog (controlled by ec) + // where we just do the stores and no loads n times : drain the pipe + // (we exit the loop when ec=1). // // The initialization of the prolog is done via the predicate registers: - // the choice of pr19 DEPENDS on the depth of the pipeline (n). + // the choice of EPI DEPENDS on the depth of the pipeline (n). // When lc > 0 pr63=1 and it is fed back into pr16 and pr16-pr62 // are then shifted right at every iteration, - // Thus by initializing pr16=1 and pr17-19=0 (19=16+4-1) before the loop - // we get pr19=1 after 4 iterations (n in our case). + // Thus by initializing pr16=1 and the rest to 0 before the loop + // we get EPI=1 after n iterations. // 1: // engage loop now, let the magic happen... (p16) ld8 t1[0]=[src1],16 // new data on top of pipeline in 1st stream (p16) ld8 t2[0]=[src2],16 // new data on top of pipeline in 2nd stream nop.i 0x0 -(p19) st8 [tgt1]=t1[3],16 // store top of 1st pipeline -(p19) st8 [tgt2]=t2[3],16 // store top of 2nd pipeline +(EPI) st8 [tgt1]=t1[PIPE_DEPTH-1],16 // store top of 1st pipeline +(EPI) st8 [tgt2]=t2[PIPE_DEPTH-1],16 // store top of 2nd pipeline br.ctop.dptk.few 1b // once lc==0, ec-- & p16=0 // stores but no loads anymore ;; diff --git a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S index 58c92876f..3743174ba 100644 --- a/arch/ia64/lib/copy_user.S +++ b/arch/ia64/lib/copy_user.S @@ -1,3 +1,34 @@ +/* + * + * Optimized version of the copy_user() routine. + * It is used to copy date across the kernel/user boundary. + * + * The source and destination are always on opposite side of + * the boundary. When reading from user space we must catch + * faults on loads. When writing to user space we must catch + * errors on stores. Note that because of the nature of the copy + * we don't need to worry about overlapping regions. + * + * + * Inputs: + * in0 address of source buffer + * in1 address of destination buffer + * in2 number of bytes to copy + * + * Outputs: + * ret0 0 in case of sucess. The number of bytes NOT copied in + * case of error. + * + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com> + * + * Fixme: + * - handle the case where we have more than 16 bytes and the alignment + * are different. + * - more benchmarking + * - fix extraneous stop bit introduced by the EX() macro. + */ + // The label comes first because our store instruction contains a comma // and confuse the preprocessor otherwise // diff --git a/arch/ia64/lib/strncpy_from_user.S b/arch/ia64/lib/strncpy_from_user.S index 17f71f1a0..f2d40984a 100644 --- a/arch/ia64/lib/strncpy_from_user.S +++ b/arch/ia64/lib/strncpy_from_user.S @@ -1,6 +1,5 @@ /* - * Just like strncpy() except for the return value. If no fault occurs during - * the copying, the number of bytes copied is returned. If a fault occurs, + * Just like strncpy() except that if a fault occurs during copying, * -EFAULT is returned. * * Inputs: @@ -10,8 +9,11 @@ * Outputs: * r8: -EFAULT in case of fault or number of bytes copied if no fault * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> + * + * 00/03/06 D. Mosberger Fixed to return proper return value (bug found by + * by Andreas Schwab <schwab@suse.de>). */ #define EX(x...) \ @@ -30,24 +32,26 @@ .global __strncpy_from_user .proc __strncpy_from_user __strncpy_from_user: - alloc r11=ar.pfs,3,0,0,0 + alloc r2=ar.pfs,3,0,0,0 + mov r8=0 mov r9=in1 + ;; add r10=in1,in2 + cmp.eq p6,p0=r0,in2 +(p6) br.ret.spnt.many rp // XXX braindead copy loop---this needs to be optimized .Loop1: - EX(ld1 r8=[in1],1) + EX(ld1 r8=[in1],1;; st1 [in0]=r8,1; cmp.ne p6,p7=r8,r0) ;; - st1 [in0]=r8,1 - cmp.ltu p6,p0=in1,r10 +(p6) cmp.ne.unc p8,p0=in1,r10 +(p8) br.cond.dpnt.few .Loop1 ;; -(p6) cmp.ne.and p6,p0=r8,r0 - ;; -(p6) br.cond.dpnt.few .Loop1 +(p6) mov r8=in2 // buffer filled up---return buffer length +(p7) sub r8=in1,r9,1 // return string length (excluding NUL character) + br.ret.sptk.few rp -1: sub r8=in1,r9 // length of string (including NUL character) .Lexit: - mov ar.pfs=r11 br.ret.sptk.few rp .endp __strncpy_from_user diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 388f1fe0c..3a630ca8c 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -241,13 +241,13 @@ put_gate_page (struct page *page, unsigned long address) pmd = pmd_alloc(pgd, address); if (!pmd) { __free_page(page); - oom(current); + panic("Out of memory."); return 0; } pte = pte_alloc(pmd, address); if (!pte) { __free_page(page); - oom(current); + panic("Out of memory."); return 0; } if (!pte_none(*pte)) { diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 72ece4147..568f7a347 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -97,7 +97,7 @@ __flush_tlb_all (void) stride0 = ia64_ptce_info.stride[0]; stride1 = ia64_ptce_info.stride[1]; - save_and_cli(flags); + __save_and_cli(flags); for (i = 0; i < count0; ++i) { for (j = 0; j < count1; ++j) { asm volatile ("ptc.e %0" :: "r"(addr)); @@ -105,7 +105,7 @@ __flush_tlb_all (void) } addr += stride0; } - restore_flags(flags); + __restore_flags(flags); ia64_insn_group_barrier(); ia64_srlz_i(); /* srlz.i implies srlz.d */ ia64_insn_group_barrier(); diff --git a/arch/mips/config.in b/arch/mips/config.in index 189a2126b..c26394e33 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.42 2000/02/24 00:12:40 ralf Exp $ +# $Id: config.in,v 1.43 2000/03/12 10:07:55 harald Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -272,7 +272,7 @@ fi source drivers/usb/Config.in -source drivers/misc/Config.in +#source drivers/misc/Config.in source fs/Config.in diff --git a/arch/mips/defconfig b/arch/mips/defconfig index bec96e794..1fda5e771 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -177,7 +177,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_SGIWD93=y CONFIG_SCSI_SGIWD93=y -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -270,7 +269,6 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -294,10 +292,6 @@ CONFIG_PSMOUSE=y # CONFIG_USB is not set # -# Misc devices -# - -# # File systems # # CONFIG_QUOTA is not set diff --git a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation index 4cc592e43..0eda6e9fc 100644 --- a/arch/mips/defconfig-decstation +++ b/arch/mips/defconfig-decstation @@ -177,6 +177,8 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_DECNCR=y # CONFIG_SCSI_DECSII is not set +CONFIG_SCSI_DECNCR=y +# CONFIG_SCSI_DECSII is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -211,7 +213,6 @@ CONFIG_SCSI_DECNCR=y # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # # I2O device support @@ -243,6 +244,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_UNIX98_PTYS is not set # CONFIG_KEYBOARD is not set # CONFIG_MOUSE is not set +# CONFIG_RTC is not set # # USB support @@ -250,10 +252,6 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_USB is not set # -# Misc devices -# - -# # File systems # # CONFIG_QUOTA is not set diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 index 5516700c1..1fda5e771 100644 --- a/arch/mips/defconfig-ip22 +++ b/arch/mips/defconfig-ip22 @@ -176,6 +176,7 @@ CONFIG_SCSI_CONSTANTS=y # SCSI low-level drivers # CONFIG_SCSI_SGIWD93=y +CONFIG_SCSI_SGIWD93=y # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -210,7 +211,6 @@ CONFIG_SCSI_SGIWD93=y # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # # I2O device support @@ -292,10 +292,6 @@ CONFIG_PSMOUSE=y # CONFIG_USB is not set # -# Misc devices -# - -# # File systems # # CONFIG_QUOTA is not set diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 0d0fac150..eca74b629 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.25 2000/03/07 15:45:28 ralf Exp $ +/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $ * * sysirix.c: IRIX system call emulation. * @@ -725,8 +725,6 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, int len, int fs_type) { struct dentry *dentry; - struct inode *inode; - mm_segment_t old_fs; struct statfs kbuf; int error, i; @@ -745,11 +743,7 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, if (IS_ERR(dentry)) goto out; - inode = dentry->d_inode; - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(dentry->d_inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -775,9 +769,7 @@ out: asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) { - struct inode *inode; struct statfs kbuf; - mm_segment_t old_fs; struct file *file; int error, i; @@ -790,23 +782,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) goto out; } - if (!(inode = file->f_dentry->d_inode)) { - error = -ENOENT; - goto out_f; - } - if (!inode->i_sb) { - error = -ENODEV; - goto out_f; - } - if (!inode->i_sb->s_op->statfs) { - error = -ENOSYS; - goto out_f; - } - - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); if (error) goto out_f; @@ -1507,8 +1483,6 @@ struct irix_statvfs { asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) { struct dentry *dentry; - struct inode *inode; - mm_segment_t old_fs; struct statfs kbuf; int error, i; @@ -1522,16 +1496,7 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) error = PTR_ERR(dentry); if(!IS_ERR(dentry)) goto out; - inode = dentry->d_inode; - - error = -ENOSYS; - if(!inode->i_sb->s_op->statfs) - goto dput_and_out; - - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(dentry->d_inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -1566,8 +1531,6 @@ out: asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) { - struct inode *inode; - mm_segment_t old_fs; struct statfs kbuf; struct file *file; int error, i; @@ -1583,23 +1546,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) error = -EBADF; goto out; } - if (!(inode = file->f_dentry->d_inode)) { - error = -ENOENT; - goto out_f; - } - if (!inode->i_sb) { - error = -ENODEV; - goto out_f; - } - if (!inode->i_sb->s_op->statfs) { - error = -ENOSYS; - goto out_f; - } - - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); if (error) goto out_f; @@ -1811,8 +1758,6 @@ struct irix_statvfs64 { asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) { struct dentry *dentry; - struct inode *inode; - mm_segment_t old_fs; struct statfs kbuf; int error, i; @@ -1826,15 +1771,7 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) error = PTR_ERR(dentry); if(IS_ERR(dentry)) goto out; - error = -ENOSYS; - inode = dentry->d_inode; - if(!inode->i_sb->s_op->statfs) - goto dput_and_out; - - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(dentry->d_inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -1869,8 +1806,6 @@ out: asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) { - struct inode *inode; - mm_segment_t old_fs; struct statfs kbuf; struct file *file; int error, i; @@ -1886,23 +1821,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) error = -EBADF; goto out; } - if (!(inode = file->f_dentry->d_inode)) { - error = -ENOENT; - goto out_f; - } - if (!inode->i_sb) { - error = -ENODEV; - goto out_f; - } - if (!inode->i_sb->s_op->statfs) { - error = -ENOSYS; - goto out_f; - } - - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); if (error) goto out_f; diff --git a/arch/mips64/config.in b/arch/mips64/config.in index 179f4f74d..be0501f60 100644 --- a/arch/mips64/config.in +++ b/arch/mips64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.14 2000/02/18 11:06:20 ulfc Exp $ +# $Id: config.in,v 1.15 2000/03/09 15:38:28 ralf Exp $ # # For a description of the syntax of this configuration file, # see the Configure script. @@ -174,7 +174,6 @@ source drivers/char/Config.in source drivers/usb/Config.in -# drivers/misc has currently only i386 specific devices. #source drivers/misc/Config.in source fs/Config.in diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig index 21623e01f..f34f2e63a 100644 --- a/arch/mips64/defconfig +++ b/arch/mips64/defconfig @@ -54,7 +54,9 @@ CONFIG_BINFMT_ELF32=y # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y CONFIG_PCI_NAMES=y # @@ -112,6 +114,7 @@ CONFIG_SKB_LARGE=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # # Telephony Support @@ -144,6 +147,7 @@ CONFIG_SD_EXTRA_DEVS=40 # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -306,7 +310,6 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -389,5 +392,6 @@ CONFIG_KCORE_ELF=y # Kernel hacking # CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 index 21623e01f..f34f2e63a 100644 --- a/arch/mips64/defconfig-ip27 +++ b/arch/mips64/defconfig-ip27 @@ -54,7 +54,9 @@ CONFIG_BINFMT_ELF32=y # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y CONFIG_PCI_NAMES=y # @@ -112,6 +114,7 @@ CONFIG_SKB_LARGE=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # # Telephony Support @@ -144,6 +147,7 @@ CONFIG_SD_EXTRA_DEVS=40 # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -306,7 +310,6 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -389,5 +392,6 @@ CONFIG_KCORE_ELF=y # Kernel hacking # CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c index eb1317ca3..e74eb781a 100644 --- a/arch/mips64/kernel/mips64_ksyms.c +++ b/arch/mips64/kernel/mips64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: mips64_ksyms.c,v 1.7 2000/02/04 07:40:24 ralf Exp $ +/* $Id: mips64_ksyms.c,v 1.8 2000/02/24 00:12:41 ralf Exp $ * * Export MIPS64-specific functions needed for loadable modules. * @@ -56,8 +56,6 @@ EXPORT_SYMBOL_NOVERS(strtok); EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); @@ -83,8 +81,10 @@ EXPORT_SYMBOL(csum_partial_copy); */ EXPORT_SYMBOL(_flush_page_to_ram); EXPORT_SYMBOL(_flush_cache_all); +#ifndef CONFIG_COHERENT_IO EXPORT_SYMBOL(_dma_cache_wback_inv); EXPORT_SYMBOL(_dma_cache_inv); +#endif EXPORT_SYMBOL(invalid_pte_table); diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index 6b8378839..604205565 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -53,7 +53,6 @@ GZIP_FLAGS = -v9f OBJECTS := head.o misc.o ../coffboot/zlib.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY_ARGS = -O elf32-powerpc OBJECTS += vreset.o kbd.o of1275.o diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile index 5a7f063fc..216b289ed 100644 --- a/arch/ppc/chrpboot/Makefile +++ b/arch/ppc/chrpboot/Makefile @@ -18,7 +18,6 @@ CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS LD_ARGS = -Ttext 0x00400000 -OBJCOPY = $(CROSS_COMPILE)objcopy OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o sysmap.o LIBS = $(TOPDIR)/lib/lib.a diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile index 29a4fdc35..5c46f9540 100644 --- a/arch/ppc/coffboot/Makefile +++ b/arch/ppc/coffboot/Makefile @@ -5,14 +5,10 @@ HOSTCFLAGS = -O -I$(TOPDIR)/include -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld CFLAGS = $(CPPFLAGS) -O -fno-builtin -OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic CHRP_LD_ARGS = -Ttext 0x00400000 -GZ = gzip -9 COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig index c849bac82..bcab91ec6 100644 --- a/arch/ppc/configs/common_defconfig +++ b/arch/ppc/configs/common_defconfig @@ -1,5 +1,5 @@ # -# Automatically generated make config: don't edit +# Automatically generated by make menuconfig: don't edit # # CONFIG_UID16 is not set @@ -33,7 +33,6 @@ CONFIG_KMOD=y # # General setup # -# CONFIG_PCI is not set CONFIG_PCI=y CONFIG_PCI=y CONFIG_NET=y @@ -46,6 +45,10 @@ CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y @@ -53,6 +56,7 @@ CONFIG_FB_COMPAT_XPMAC=y CONFIG_PMAC_PBOOK=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set CONFIG_ADB=y CONFIG_ADB_CUDA=y CONFIG_ADB_MACIO=y @@ -69,27 +73,21 @@ CONFIG_BOOTX_TEXT=y # Plug and Play configuration # # CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=y - -# -# IDE chipset support/bugfixes -# # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y @@ -108,10 +106,6 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_AUTO=y # CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_CPQ_DA is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set @@ -144,18 +138,10 @@ CONFIG_IP_MULTICAST=y # CONFIG_IP_MROUTE is not set CONFIG_IP_ALIAS=y CONFIG_SYN_COOKIES=y - -# -# (it is safe to leave these untouched) -# CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set - -# -# -# # CONFIG_IPX is not set CONFIG_ATALK=m # CONFIG_DECNET is not set @@ -177,10 +163,6 @@ CONFIG_ATALK=m # SCSI support # CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y @@ -189,10 +171,6 @@ CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y @@ -272,6 +250,13 @@ CONFIG_NETDEVICES=y # ARCnet devices # # CONFIG_ARCNET is not set + +# +# Appletalk devices +# +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +# CONFIG_IPDDP is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -299,6 +284,7 @@ CONFIG_PCNET32=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set CONFIG_DE4X5=y # CONFIG_TULIP is not set # CONFIG_DGRS is not set @@ -324,13 +310,6 @@ CONFIG_DE4X5=y # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set - -# -# Appletalk devices -# -# CONFIG_LTPC is not set -# CONFIG_COPS is not set -# CONFIG_IPDDP is not set CONFIG_PPP=y # CONFIG_PPP_ASYNC is not set # CONFIG_PPP_SYNC_TTY is not set @@ -344,7 +323,7 @@ CONFIG_PPP=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -397,7 +376,7 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y -# CONFIG_FB_ATY128 is not set +CONFIG_FB_ATY128=y CONFIG_FB_3DFX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -456,7 +435,6 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set CONFIG_NVRAM=y # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -471,28 +449,17 @@ CONFIG_NVRAM=y # # CONFIG_FTAPE is not set # CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set # # USB support # CONFIG_USB=y - -# -# USB Controllers -# # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=y - -# -# Miscellaneous USB options -# # CONFIG_USB_DEVICEFS is not set - -# -# USB Devices -# # CONFIG_USB_PRINTER is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_AUDIO is not set @@ -503,14 +470,11 @@ CONFIG_USB_OHCI=y # CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set # CONFIG_USB_STORAGE is not set +# CONFIG_USB_USS720 is not set # CONFIG_USB_DABUSB is not set # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RIO500 is not set - -# -# USB HID -# # CONFIG_USB_HID is not set CONFIG_USB_KBD=y CONFIG_USB_MOUSE=y @@ -546,6 +510,7 @@ CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -559,6 +524,7 @@ CONFIG_EXT2_FS=y # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y @@ -630,7 +596,6 @@ CONFIG_DMASOUND=y # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=y -# CONFIG_SOUND_DMAP is not set # CONFIG_SOUND_AD1816 is not set # CONFIG_SOUND_SGALAXY is not set CONFIG_SOUND_CS4232=m @@ -643,7 +608,9 @@ CONFIG_SOUND_CS4232=m # CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set # CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set # CONFIG_SOUND_PSS is not set +# CONFIG_PSS_HAVE_BOOT is not set # CONFIG_SOUND_SOFTOSS is not set # CONFIG_SOUND_SB is not set # CONFIG_SOUND_WAVEFRONT is not set diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index c849bac82..bcab91ec6 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -1,5 +1,5 @@ # -# Automatically generated make config: don't edit +# Automatically generated by make menuconfig: don't edit # # CONFIG_UID16 is not set @@ -33,7 +33,6 @@ CONFIG_KMOD=y # # General setup # -# CONFIG_PCI is not set CONFIG_PCI=y CONFIG_PCI=y CONFIG_NET=y @@ -46,6 +45,10 @@ CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y @@ -53,6 +56,7 @@ CONFIG_FB_COMPAT_XPMAC=y CONFIG_PMAC_PBOOK=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set CONFIG_ADB=y CONFIG_ADB_CUDA=y CONFIG_ADB_MACIO=y @@ -69,27 +73,21 @@ CONFIG_BOOTX_TEXT=y # Plug and Play configuration # # CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=y - -# -# IDE chipset support/bugfixes -# # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y @@ -108,10 +106,6 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_AUTO=y # CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_CPQ_DA is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set @@ -144,18 +138,10 @@ CONFIG_IP_MULTICAST=y # CONFIG_IP_MROUTE is not set CONFIG_IP_ALIAS=y CONFIG_SYN_COOKIES=y - -# -# (it is safe to leave these untouched) -# CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set - -# -# -# # CONFIG_IPX is not set CONFIG_ATALK=m # CONFIG_DECNET is not set @@ -177,10 +163,6 @@ CONFIG_ATALK=m # SCSI support # CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y @@ -189,10 +171,6 @@ CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y @@ -272,6 +250,13 @@ CONFIG_NETDEVICES=y # ARCnet devices # # CONFIG_ARCNET is not set + +# +# Appletalk devices +# +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +# CONFIG_IPDDP is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -299,6 +284,7 @@ CONFIG_PCNET32=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set CONFIG_DE4X5=y # CONFIG_TULIP is not set # CONFIG_DGRS is not set @@ -324,13 +310,6 @@ CONFIG_DE4X5=y # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set - -# -# Appletalk devices -# -# CONFIG_LTPC is not set -# CONFIG_COPS is not set -# CONFIG_IPDDP is not set CONFIG_PPP=y # CONFIG_PPP_ASYNC is not set # CONFIG_PPP_SYNC_TTY is not set @@ -344,7 +323,7 @@ CONFIG_PPP=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -397,7 +376,7 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y -# CONFIG_FB_ATY128 is not set +CONFIG_FB_ATY128=y CONFIG_FB_3DFX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -456,7 +435,6 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set CONFIG_NVRAM=y # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -471,28 +449,17 @@ CONFIG_NVRAM=y # # CONFIG_FTAPE is not set # CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set # # USB support # CONFIG_USB=y - -# -# USB Controllers -# # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=y - -# -# Miscellaneous USB options -# # CONFIG_USB_DEVICEFS is not set - -# -# USB Devices -# # CONFIG_USB_PRINTER is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_AUDIO is not set @@ -503,14 +470,11 @@ CONFIG_USB_OHCI=y # CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set # CONFIG_USB_STORAGE is not set +# CONFIG_USB_USS720 is not set # CONFIG_USB_DABUSB is not set # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RIO500 is not set - -# -# USB HID -# # CONFIG_USB_HID is not set CONFIG_USB_KBD=y CONFIG_USB_MOUSE=y @@ -546,6 +510,7 @@ CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -559,6 +524,7 @@ CONFIG_EXT2_FS=y # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y @@ -630,7 +596,6 @@ CONFIG_DMASOUND=y # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=y -# CONFIG_SOUND_DMAP is not set # CONFIG_SOUND_AD1816 is not set # CONFIG_SOUND_SGALAXY is not set CONFIG_SOUND_CS4232=m @@ -643,7 +608,9 @@ CONFIG_SOUND_CS4232=m # CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set # CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set # CONFIG_SOUND_PSS is not set +# CONFIG_PSS_HAVE_BOOT is not set # CONFIG_SOUND_SOFTOSS is not set # CONFIG_SOUND_SB is not set # CONFIG_SOUND_WAVEFRONT is not set diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c index d55fa24c0..c692b54d0 100644 --- a/arch/ppc/kernel/chrp_time.c +++ b/arch/ppc/kernel/chrp_time.c @@ -173,7 +173,7 @@ void __init chrp_calibrate_decr(void) } freq *= 30; divisor = 30; - printk("time_init: decrementer frequency = %lu/%d (%d MHz)\n", freq, + printk("time_init: decrementer frequency = %lu/%d (%ld MHz)\n", freq, divisor, (freq/divisor)>>20); decrementer_count = freq / HZ / divisor; count_period_num = divisor; diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index f8e11ecc0..e4b279032 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -677,7 +677,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, err = parse_hex_value(buffer, count, &new_value); -#if CONFIG_SMP +#if 0/*CONFIG_SMP*/ /* * Do not allow disabling IRQs completely - it's a too easy * way to make the system unusable accidentally :-) At least diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 301a82ba8..9438c57ee 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -97,7 +97,7 @@ struct hw_interrupt_type open_pic = { #define check_arg_cpu(cpu) do {} while (0) #endif -static void no_action(int ir1, void *dev, struct pt_regs *regs) +void no_action(int ir1, void *dev, struct pt_regs *regs) { } @@ -301,7 +301,7 @@ void find_ISUs(void) NumSources = 0x10; #else /* for non-distributed OpenPIC implementations it's in the IDU -- Cort */ - ISU = OpenPIC->Source; + ISU = (OpenPIC_Source *)OpenPIC->Source; #endif } diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c index 310e301e6..a987b8fd6 100644 --- a/arch/ppc/kernel/prom.c +++ b/arch/ppc/kernel/prom.c @@ -114,9 +114,6 @@ static struct device_node *allnodes = 0; static void clearscreen(void); static void flushscreen(void); -void prom_drawchar(char c); -void prom_drawstring(const char *c); -void prom_drawhex(unsigned long v); static void scrollscreen(void); static void draw_byte(unsigned char c, long locX, long locY); diff --git a/arch/ppc/mbxboot/Makefile b/arch/ppc/mbxboot/Makefile index 0a70462a7..59b95c5df 100644 --- a/arch/ppc/mbxboot/Makefile +++ b/arch/ppc/mbxboot/Makefile @@ -27,11 +27,9 @@ ISZ = 0 TFTPIMAGE=/tftpboot/zImage.mbx ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000 -GZIP_FLAGS = -v9 OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx -OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY_ARGS = -O elf32-powerpc ifeq ($(CONFIG_MBX),y) diff --git a/arch/ppc/treeboot/Makefile b/arch/ppc/treeboot/Makefile index f84810e1e..7d42a6741 100644 --- a/arch/ppc/treeboot/Makefile +++ b/arch/ppc/treeboot/Makefile @@ -10,11 +10,6 @@ HOSTCFLAGS = -O -I$(TOPDIR)/include -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld -OBJCOPY = $(CROSS_COMPILE)objcopy -OBJDUMP = $(CROSS_COMPILE)objdump - GZIP = gzip -vf9 RM = rm -f MKEVIMG = mkevimg -l diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 620df9aea..b81e21890 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -7,6 +7,7 @@ #include <linux/sched.h> #include <asm/ptrace.h> #include <asm/string.h> +#include <asm/prom.h> #include "nonstdio.h" #include "privinst.h" @@ -81,7 +82,7 @@ static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned pc); static void bpt_cmds(void); static void cacheflush(void); -static char *pretty_lookup_name(unsigned long addr); +static char *pretty_print_addr(unsigned long addr); static char *lookup_name(unsigned long addr); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned); @@ -141,7 +142,7 @@ xmon(struct pt_regs *excp) prom_drawstring(" msr="); prom_drawhex(excp->msr); prom_drawstring(" trap="); prom_drawhex(excp->trap); prom_drawstring(" sp="); prom_drawhex(excp->gpr[1]); - sp = &excp->gpr[0]; + sp = (unsigned *)&excp->gpr[0]; for (i = 0; i < 32; ++i) { if ((i & 7) == 0) prom_drawstring("\n"); @@ -544,10 +545,10 @@ getsp() void excprint(struct pt_regs *fp) { - printf("vector: %x at pc = %x %s", - fp->trap, fp->nip, pretty_lookup_name(fp->nip)); - printf(", msr = %x, sp = %x [%x]\n", - fp->msr, fp->gpr[1], fp); + printf("vector: %x at pc = %x", + fp->trap, fp->nip); + printf(", lr = %x, msr = %x, sp = %x [%x]\n", + fp->link, fp->msr, fp->gpr[1], fp); if (fp->trap == 0x300 || fp->trap == 0x600) printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr); if (current) @@ -1385,25 +1386,14 @@ char *str; lineptr = str; } -/* - * We use this array a lot here. We assume we don't have multiple - * instances of xmon running and that we don't use the return value of - * any functions other than printing them. - * -- Cort - */ -char last[64]; -static char *pretty_lookup_name(unsigned long addr) +static char *pretty_print_addr(unsigned long addr) { + printf("%08x", addr); if ( lookup_name(addr) ) - { - sprintf(last, " (%s)", lookup_name(addr)); - return last; - } - else - return NULL; + printf(" %s", lookup_name(addr) ); + return NULL; } - static char *lookup_name(unsigned long addr) { extern char *sysmap; @@ -1413,11 +1403,8 @@ static char *lookup_name(unsigned long addr) if ( !sysmap || !sysmap_size ) return NULL; - - /* adjust if addr is relative to kernelbase */ - if ( addr < PAGE_OFFSET ) - addr += PAGE_OFFSET; - +return NULL; +#if 0 cmp = simple_strtoul(c, &c, 8); strcpy( last, strsep( &c, "\n")); while ( c < (sysmap+sysmap_size) ) @@ -1427,6 +1414,7 @@ static char *lookup_name(unsigned long addr) break; strcpy( last, strsep( &c, "\n")); } - return last; + return NULLlast; +#endif } diff --git a/arch/sh/config.in b/arch/sh/config.in index 8b74eeafa..fd858e00e 100644 --- a/arch/sh/config.in +++ b/arch/sh/config.in @@ -155,7 +155,7 @@ if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then source drivers/char/pcmcia/Config.in fi -source drivers/misc/Config.in +#source drivers/misc/Config.in source fs/Config.in diff --git a/arch/sh/defconfig b/arch/sh/defconfig index 5fabcdedc..ea5851d39 100644 --- a/arch/sh/defconfig +++ b/arch/sh/defconfig @@ -96,10 +96,6 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_UNIX98_PTYS is not set # -# Misc devices -# - -# # Filesystems # # CONFIG_QUOTA is not set diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index 580d004d7..e719d9214 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -83,6 +83,10 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_SUNOS_EMUL=y + +# +# Parallel port support +# # CONFIG_PARPORT is not set # CONFIG_PRINTER is not set @@ -146,7 +150,6 @@ CONFIG_ATALK=m CONFIG_DECNET=m CONFIG_DECNET_SIOCGIFCONF=y # CONFIG_DECNET_ROUTER is not set -CONFIG_DECNET_RAW=y # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index d4585d9d5..e0bb41045 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.93 2000/02/26 11:02:45 anton Exp $ +/* $Id: sparc_ksyms.c,v 1.94 2000/02/28 04:00:53 anton Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -107,16 +107,10 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_exit); EXPORT_SYMBOL_PRIVATE(_rw_write_enter); #endif #ifdef __SMP__ -#ifdef DEBUG_IRQLOCK EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_cli); -#else -EXPORT_SYMBOL_PRIVATE(_global_restore_flags); -EXPORT_SYMBOL_PRIVATE(_global_sti); -EXPORT_SYMBOL_PRIVATE(_global_cli); -#endif #endif /* rw semaphores */ diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 54c701768..1d6f208f6 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.113 2000/02/16 07:31:29 davem Exp $ +/* $Id: sys_sunos.c,v 1.114 2000/03/07 22:27:27 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 1a8c404e2..d269e148b 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.31 1999/12/28 11:50:39 jj Exp $ +# $Id: Makefile,v 1.32 2000/02/28 04:00:48 anton Exp $ # Makefile for Sparc library files.. # @@ -8,10 +8,6 @@ OBJS = mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \ ashldi3.o rwsem.o -ifdef CONFIG_SMP -OBJS += irqlock.o -endif - lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) sync diff --git a/arch/sparc/lib/irqlock.S b/arch/sparc/lib/irqlock.S deleted file mode 100644 index 4c41e9825..000000000 --- a/arch/sparc/lib/irqlock.S +++ /dev/null @@ -1,122 +0,0 @@ -/* $Id: irqlock.S,v 1.5 1999/04/20 13:22:37 anton Exp $ - * irqlock.S: High performance IRQ global locking and interrupt entry. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <asm/psr.h> -#include <asm/smp.h> - - .text - .align 4 - - /* Weird calling conventions... %g7=flags, %g4=%prev_o7 - * Very clever for the __global_sti case, the inline which - * gets us here clears %g7 and it just works. - */ - .globl ___global_restore_flags, ___global_sti, ___global_cli -___global_restore_flags: - bne,a ___global_cli - rd %tbr, %g7 - rd %tbr, %g2 - -___global_sti: - sethi %hi(global_irq_holder), %g1 - sethi %hi(global_irq_lock), %g3 - srl %g2, 12, %g2 - ldub [%g1 + %lo(global_irq_holder)], %g5 - and %g2, 3, %g2 - cmp %g5, %g2 - bne 1f - mov NO_PROC_ID, %g5 - stb %g5, [%g1 + %lo(global_irq_holder)] - stb %g0, [%g3 + %lo(global_irq_lock)] -1: - rd %psr, %g3 - andcc %g7, 2, %g0 - bne,a 1f - or %g3, PSR_PIL, %g3 - andn %g3, PSR_PIL, %g3 -1: - wr %g3, 0x0, %psr - nop -__global_cli_out: ! All togther now... "fuuunnnnn" - retl - mov %g4, %o7 - -__spin_on_global_irq_lock: - orcc %g2, 0x0, %g0 - bne,a __spin_on_global_irq_lock - ldub [%g1], %g2 - b,a 1f - - /* This is a royal pain in the ass to make fast... 8-( */ -___global_cli: - sethi %hi(global_irq_lock), %g5 - srl %g7, 12, %g7 - sethi %hi(global_irq_holder), %g3 - and %g7, 3, %g7 - ldub [%g3 + %lo(global_irq_holder)], %g1 - rd %psr, %g2 - cmp %g1, %g7 - or %g2, PSR_PIL, %g2 - be __global_cli_out - wr %g2, 0x0, %psr ! XXX some sparcs may choke on this... - sethi %hi(local_irq_count), %g3 - or %g3, %lo(local_irq_count), %g3 - or %g5, %lo(global_irq_lock), %g1 -1: - ldstub [%g1], %g2 - orcc %g2, 0x0, %g0 - bne,a __spin_on_global_irq_lock - ldub [%g1], %g2 -__wait_on_irq: - sll %g7, 2, %g7 - ld [%g3 + %g7], %g2 - sethi %hi(global_irq_count), %g1 - or %g1, %lo(global_irq_count), %g1 - srl %g7, 2, %g7 - ld [%g1], %g5 - sra %g5, 8, %g5 -__wait_on_irq_loop: - cmp %g5, %g2 - sethi %hi(global_irq_holder), %g3 - be,a __global_cli_out ! Mamamia, Mamamia, this is the fast path - stb %g7, [%g3 + %lo(global_irq_holder)] -1: - ldstub [%g1 + 3], %g3 - orcc %g3, 0x0, %g0 - bne 1b - ld [%g1], %g3 - sra %g3, 8, %g3 - sub %g3, %g2, %g3 - sll %g3, 8, %g3 - st %g3, [%g1] - sethi %hi(global_irq_lock), %g3 - stb %g0, [%g3 + %lo(global_irq_lock)] -0: - ld [%g1], %g5 -9: - ldub [%g3 + %lo(global_irq_lock)], %g3 - sra %g5, 8, %g5 - orcc %g3, %g5, %g0 - bne 0b - sethi %hi(global_irq_lock), %g3 - ldstub [%g3 + %lo(global_irq_lock)], %g5 - orcc %g5, 0x0, %g0 - bne,a 9b - ld [%g1], %g5 -1: - ldstub [%g1 + 3], %g3 - orcc %g3, 0x0, %g0 - bne 1b - ld [%g1], %g3 - sra %g3, 8, %g3 - add %g3, %g2, %g5 - sll %g5, 8, %g3 - b __wait_on_irq_loop - st %g3, [%g1] - -#if 0 /* XXX I'm not delirious enough to debug this yet. */ - add %o7, (8 + (__wait_on_irq_loop - . - 4)), %o7 ! AIEEEEE -#endif diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 3ac49a10b..d92fbbb0b 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.81 2000/02/26 11:59:31 anton Exp $ +/* $Id: init.c,v 1.83 2000/03/07 23:12:35 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -121,8 +121,8 @@ unsigned long __init bootmem_init(void) int i; /* Limit maximum memory until we implement highmem for sparc */ - if (cmdline_memory_size > 0x9000000) - cmdline_memory_size = 0x9000000; + if (!cmdline_memory_size || cmdline_memory_size > 0x0d000000) + cmdline_memory_size = 0x0d000000; /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted @@ -138,7 +138,7 @@ unsigned long __init bootmem_init(void) sp_banks[i].num_bytes; if (cmdline_memory_size) { if (end_of_phys_memory > cmdline_memory_size) { - if (cmdline_memory_size > sp_banks[i].base_addr) { + if (cmdline_memory_size < sp_banks[i].base_addr) { end_of_phys_memory = sp_banks[i-1].base_addr + sp_banks[i-1].num_bytes; diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index 4f51537e2..868dd6851 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.41 1999/12/21 04:02:23 davem Exp $ +# $Id: Makefile,v 1.42 2000/03/09 05:56:43 jj Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -14,8 +14,9 @@ SHELL =/bin/bash CC := sparc64-linux-gcc -IS_EGCS := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) +NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) +UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; ) ifneq ($(NEW_GAS),y) AS = sparc64-linux-as @@ -28,19 +29,26 @@ AS := $(AS) -64 LD := $(LD) -m elf64_sparc endif ELFTOAOUT = elftoaout +ifneq ($(UNDECLARED_REGS),y) +CC_UNDECL = +else +CC_UNDECL = -Wa,--undeclared-regs +AS := $(AS) --undeclared-regs +endif # # Uncomment the first CFLAGS if you are doing kgdb source level # debugging of the kernel to get the proper debugging information. #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 -ifneq ($(IS_EGCS),y) +ifneq ($(NEW_GCC),y) CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare else CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ - -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare - AFLAGS += -m64 -mcpu=ultrasparc + -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare \ + $(CC_UNDECL) + AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) endif # Uncomment this to get spinlock/rwlock debugging on SMP. diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 7e7a45a70..a61d4d049 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -97,6 +97,10 @@ CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m # CONFIG_SUNOS_EMUL is not set CONFIG_SOLARIS_EMUL=m + +# +# Parallel port support +# CONFIG_PARPORT=m CONFIG_PARPORT_PC=m CONFIG_PARPORT_PC_FIFO=y @@ -176,7 +180,6 @@ CONFIG_ATALK=m CONFIG_DECNET=m CONFIG_DECNET_SIOCGIFCONF=y # CONFIG_DECNET_ROUTER is not set -CONFIG_DECNET_RAW=y # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 00f635ab3..d7267880a 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -1,4 +1,4 @@ -/* $Id: pci_iommu.c,v 1.10 2000/02/18 13:48:54 davem Exp $ +/* $Id: pci_iommu.c,v 1.11 2000/03/10 02:42:15 davem Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -34,46 +34,96 @@ : "r" (__val), "r" (__reg), \ "i" (ASI_PHYS_BYPASS_EC_E)) +/* Must be invoked under the IOMMU lock. */ +static void __iommu_flushall(struct pci_iommu *iommu) +{ + unsigned long tag; + int entry; + + tag = iommu->iommu_flush + (0xa580UL - 0x0210UL); + for (entry = 0; entry < 16; entry++) { + pci_iommu_write(tag, 0); + tag += 8; + } + + /* Ensure completion of previous PIO writes. */ + (void) pci_iommu_read(iommu->write_complete_reg); + + /* Now update everyone's flush point. */ + for (entry = 0; entry < PBM_NCLUSTERS; entry++) { + iommu->alloc_info[entry].flush = + iommu->alloc_info[entry].next; + } +} + static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) { - iopte_t *iopte; - unsigned long cnum, ent; + iopte_t *iopte, *limit; + unsigned long cnum, ent, flush_point; cnum = 0; while ((1UL << cnum) < npages) cnum++; - iopte = iommu->page_table + (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); - iopte += ((ent = iommu->lowest_free[cnum]) << cnum); + iopte = (iommu->page_table + + (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); - if (iopte_val(iopte[(1UL << cnum)]) == 0UL) { - /* Fast path. */ - iommu->lowest_free[cnum] = ent + 1; - } else { - unsigned long pte_off = 1; + if (cnum == 0) + limit = (iommu->page_table + + iommu->lowest_consistent_map); + else + limit = (iopte + + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); - ent += 1; - do { - pte_off++; - ent++; - } while (iopte_val(iopte[(pte_off << cnum)]) != 0UL); - iommu->lowest_free[cnum] = ent; + iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); + flush_point = iommu->alloc_info[cnum].flush; + + for (;;) { + if (iopte_val(*iopte) == 0UL) { + if ((iopte + (1 << cnum)) >= limit) + ent = 0; + else + ent = ent + 1; + iommu->alloc_info[cnum].next = ent; + if (ent == flush_point) + __iommu_flushall(iommu); + break; + } + iopte += (1 << cnum); + ent++; + if (iopte >= limit) { + iopte = (iommu->page_table + + (cnum << + (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); + ent = 0; + } + if (ent == flush_point) + __iommu_flushall(iommu); } /* I've got your streaming cluster right here buddy boy... */ return iopte; } -static inline void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages) +static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, + unsigned long npages, unsigned long ctx) { unsigned long cnum, ent; cnum = 0; while ((1UL << cnum) < npages) cnum++; + ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) >> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits); - if (ent < iommu->lowest_free[cnum]) - iommu->lowest_free[cnum] = ent; + + /* If the global flush might not have caught this entry, + * adjust the flush point such that we will flush before + * ever trying to reuse it. + */ +#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y))) + if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush)) + iommu->alloc_info[cnum].flush = ent; +#undef between } /* We allocate consistent mappings from the end of cluster zero. */ @@ -92,8 +142,13 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long if (iopte_val(*iopte) & IOPTE_VALID) break; } - if (tmp == 0) + if (tmp == 0) { + u32 entry = (iopte - iommu->page_table); + + if (entry < iommu->lowest_consistent_map) + iommu->lowest_consistent_map = entry; return iopte; + } } } return NULL; @@ -182,7 +237,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ struct pcidev_cookie *pcp; struct pci_iommu *iommu; iopte_t *iopte; - unsigned long flags, order, npages, i; + unsigned long flags, order, npages, i, ctx; npages = PAGE_ALIGN(size) >> PAGE_SHIFT; pcp = pdev->sysdata; @@ -192,15 +247,45 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ spin_lock_irqsave(&iommu->lock, flags); + if ((iopte - iommu->page_table) == + iommu->lowest_consistent_map) { + iopte_t *walk = iopte + npages; + iopte_t *limit; + + limit = (iommu->page_table + + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); + while (walk < limit) { + if (iopte_val(*walk) != IOPTE_INVALID) + break; + walk++; + } + iommu->lowest_consistent_map = + (walk - iommu->page_table); + } + /* Data for consistent mappings cannot enter the streaming - * buffers, so we only need to update the TSB. Flush of the - * IOTLB is done later when these ioptes are used for a new - * allocation. + * buffers, so we only need to update the TSB. We flush + * the IOMMU here as well to prevent conflicts with the + * streaming mapping deferred tlb flush scheme. */ + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; + for (i = 0; i < npages; i++, iopte++) iopte_val(*iopte) = IOPTE_INVALID; + if (iommu->iommu_ctxflush) { + pci_iommu_write(iommu->iommu_ctxflush, ctx); + } else { + for (i = 0; i < npages; i++) { + u32 daddr = dvma + (i << PAGE_SHIFT); + + pci_iommu_write(iommu->iommu_flush, daddr); + } + } + spin_unlock_irqrestore(&iommu->lock, flags); order = get_order(size); @@ -253,14 +338,6 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) iopte_val(*base) = iopte_protection | base_paddr; - /* Flush the IOMMU TLB. */ - if (iommu->iommu_ctxflush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) - pci_iommu_write(iommu->iommu_flush, bus_addr); - } - spin_unlock_irqrestore(&iommu->lock, flags); return ret; @@ -294,15 +371,15 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int spin_lock_irqsave(&iommu->lock, flags); + /* Record the context, if any. */ + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; + /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) { u32 vaddr = bus_addr; - /* Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && iommu->iommu_ctxflush) { @@ -327,10 +404,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int /* Step 2: Clear out first TSB entry. */ iopte_val(*base) = IOPTE_INVALID; - free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages); - - /* Step 3: Ensure completion of previous PIO writes. */ - (void) pci_iommu_read(iommu->write_complete_reg); + free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, + npages, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -415,7 +490,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; - unsigned long flags, ctx, i, npages, iopte_protection; + unsigned long flags, ctx, npages, iopte_protection; iopte_t *base; u32 dma_base; struct scatterlist *sgtmp; @@ -474,14 +549,6 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int verify_sglist(sglist, nelems, base, npages); #endif - /* Step 6: Flush the IOMMU TLB. */ - if (iommu->iommu_ctxflush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - for (i = 0; i < npages; i++, dma_base += PAGE_SIZE) - pci_iommu_write(iommu->iommu_flush, dma_base); - } - spin_unlock_irqrestore(&iommu->lock, flags); return used; @@ -522,15 +589,15 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, spin_lock_irqsave(&iommu->lock, flags); + /* Record the context, if any. */ + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; + /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) { u32 vaddr = bus_addr; - /* Record the context, if any. */ - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && iommu->iommu_ctxflush) { @@ -555,10 +622,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, /* Step 2: Clear out first TSB entry. */ iopte_val(*base) = IOPTE_INVALID; - free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages); - - /* Step 3: Ensure completion of previous PIO writes. */ - (void) pci_iommu_read(iommu->write_complete_reg); + free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, + npages, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index b3248de39..1c8f59f3f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.13 2000/02/18 13:48:54 davem Exp $ +/* $Id: pci_psycho.c,v 1.14 2000/03/10 02:42:15 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1246,11 +1246,14 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL); control |= PSYCHO_IOMMU_CTRL_DENAB; psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for(i = 0; i < 16; i++) + for(i = 0; i < 16; i++) { + psycho_write(p->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); + } - control &= ~(PSYCHO_IOMMU_CTRL_DENAB); - psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control); + /* Leave diag mode enabled for full-flushing done + * in pci_iommu.c + */ /* Using assumed page size 8K with 128K entries we need 1MB iommu page * table (128K ioptes * 8 bytes per iopte). This is @@ -1267,9 +1270,14 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) p->iommu.dma_addr_mask = 0xffffffff; memset((char *)tsbbase, 0, PAGE_SIZE << 7); - /* Make sure DMA address 0 is never returned just to allow catching - of buggy drivers. */ - p->iommu.lowest_free[0] = 1; + /* We start with no consistent mappings. */ + p->iommu.lowest_consistent_map = + 1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS); + + for (i = 0; i < PBM_NCLUSTERS; i++) { + p->iommu.alloc_info[i].flush = 0; + p->iommu.alloc_info[i].next = 0; + } psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase)); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index e96af490d..a10f5f072 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.14 2000/02/18 13:48:55 davem Exp $ +/* $Id: pci_sabre.c,v 1.15 2000/03/10 02:42:16 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1128,11 +1128,14 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, control |= SABRE_IOMMUCTRL_DENAB; sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); - for(i = 0; i < 16; i++) + for(i = 0; i < 16; i++) { + sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); + } - control &= ~(SABRE_IOMMUCTRL_DENAB); - sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); + /* Leave diag mode enabled for full-flushing done + * in pci_iommu.c + */ tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8)); if (!tsbbase) { @@ -1144,10 +1147,6 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, p->iommu.dma_addr_mask = dma_mask; memset((char *)tsbbase, 0, PAGE_SIZE << order); - /* Make sure DMA address 0 is never returned just to allow catching - of buggy drivers. */ - p->iommu.lowest_free[0] = 1; - sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL); @@ -1168,6 +1167,15 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, break; } sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); + + /* We start with no consistent mappings. */ + p->iommu.lowest_consistent_map = + 1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS); + + for (i = 0; i < PBM_NCLUSTERS; i++) { + p->iommu.alloc_info[i].flush = 0; + p->iommu.alloc_info[i].next = 0; + } } static void __init pbm_register_toplevel_resources(struct pci_controller_info *p, diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 1b454fa2c..c9a0d4a59 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.9 2000/02/18 13:48:57 davem Exp $ +/* $Id: sbus.c,v 1.10 2000/03/10 07:52:08 davem Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -53,13 +53,18 @@ struct sbus_iommu { * you must increase the size of the type of * these counters. You have been duly warned. -DaveM */ -/*0x30*/u16 lowest_free[NCLUSTERS]; +/*0x30*/struct { + u16 next; + u16 flush; + } alloc_info[NCLUSTERS]; + + /* The lowest used consistent mapping entry. Since + * we allocate consistent maps out of cluster 0 this + * is relative to the beginning of closter 0. + */ +/*0x50*/u32 lowest_consistent_map; }; -/* Flushing heuristics */ -#define IOMMU_DIAG_LIM 16 -#define STRBUF_DIAG_LIM 32 - /* Offsets from iommu_regs */ #define SYSIO_IOMMUREG_BASE 0x2400UL #define IOMMU_CONTROL (0x2400UL - 0x2400UL) /* IOMMU control register */ @@ -73,49 +78,29 @@ struct sbus_iommu { #define IOMMU_DRAM_VALID (1UL << 30UL) -static void __iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) +static void __iommu_flushall(struct sbus_iommu *iommu) { - int hit = 0; - - if (npages <= IOMMU_DIAG_LIM) { - while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), - iommu->iommu_regs + IOMMU_FLUSH); - hit = 1; - } else { - u32 limit = base + ((npages << PAGE_SHIFT) - 1UL); - unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; - unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; - int entry; + unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; + int entry; - for (entry = 0; entry < 16; entry++, dram += 8, tag += 8) { - u32 addr = ((u32)upa_readq(tag) << PAGE_SHIFT); - if (addr >= base && addr <= limit) { - u64 val = upa_readq(dram); + for (entry = 0; entry < 16; entry++) { + upa_writeq(0, tag); + tag += 8UL; + } + upa_readq(iommu->sbus_control_reg); - if (val & IOMMU_DRAM_VALID) { - upa_writeq(addr, - iommu->iommu_regs + IOMMU_FLUSH); - hit = 1; - } - } - } + for (entry = 0; entry < NCLUSTERS; entry++) { + iommu->alloc_info[entry].flush = + iommu->alloc_info[entry].next; } - if (hit != 0) - upa_readq(iommu->sbus_control_reg); } -/* In an effort to keep latency under control, we special - * case single page IOMMU flushes. - */ -static __inline__ void iommu_flush(struct sbus_iommu *iommu, - u32 base, unsigned long npages) +static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) { - if (npages == 1) { - upa_writeq(base, iommu->iommu_regs + IOMMU_FLUSH); - upa_readq(iommu->sbus_control_reg); - } else - __iommu_flush(iommu, base, npages); + while (npages--) + upa_writeq(base + (npages << PAGE_SHIFT), + iommu->iommu_regs + IOMMU_FLUSH); + upa_readq(iommu->sbus_control_reg); } /* Offsets from strbuf_regs */ @@ -132,65 +117,57 @@ static __inline__ void iommu_flush(struct sbus_iommu *iommu, static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) { - int hit = 0; - iommu->strbuf_flushflag = 0UL; - if (npages <= STRBUF_DIAG_LIM) { - while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), - iommu->strbuf_regs + STRBUF_PFLUSH); - hit = 1; - } else { - u32 limit = base + ((npages << PAGE_SHIFT) - 1UL); - unsigned long tag = iommu->strbuf_regs + STRBUF_PTAGDIAG; - int entry; - - for (entry = 0; entry < 16; entry++, tag += 8) { - u64 val = upa_readq(tag); - - if (val & STRBUF_TAG_VALID) { - u32 addr = ((u32)(val & ~3UL)) << (PAGE_SHIFT - 2UL); - if (addr >= base && addr <= limit) { - upa_writeq(addr, - iommu->strbuf_regs + STRBUF_PFLUSH); - hit = 1; - } - } - } - } - if (hit != 0) { - /* Whoopee cushion! */ - upa_writeq(__pa(&iommu->strbuf_flushflag), - iommu->strbuf_regs + STRBUF_FSYNC); - upa_readq(iommu->sbus_control_reg); - while (iommu->strbuf_flushflag == 0UL) - membar("#LoadLoad"); - } + while (npages--) + upa_writeq(base + (npages << PAGE_SHIFT), + iommu->strbuf_regs + STRBUF_PFLUSH); + + /* Whoopee cushion! */ + upa_writeq(__pa(&iommu->strbuf_flushflag), + iommu->strbuf_regs + STRBUF_FSYNC); + upa_readq(iommu->sbus_control_reg); + while (iommu->strbuf_flushflag == 0UL) + membar("#LoadLoad"); } static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) { - iopte_t *iopte; - unsigned long cnum, ent; + iopte_t *iopte, *limit; + unsigned long cnum, ent, flush_point; cnum = 0; while ((1UL << cnum) < npages) cnum++; iopte = iommu->page_table + (cnum * CLUSTER_NPAGES); - iopte += ((ent = iommu->lowest_free[cnum]) << cnum); - - if (iopte_val(iopte[(1UL << cnum)]) == 0UL) { - /* Fast path. */ - iommu->lowest_free[cnum] = ent + 1; - } else { - unsigned long pte_off = 1; - ent += 1; - do { - pte_off++; - ent++; - } while (iopte_val(iopte[(pte_off << cnum)]) != 0UL); - iommu->lowest_free[cnum] = ent; + if (cnum == 0) + limit = (iommu->page_table + + iommu->lowest_consistent_map); + else + limit = (iopte + CLUSTER_NPAGES); + + iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); + flush_point = iommu->alloc_info[cnum].flush; + + for (;;) { + if (iopte_val(*iopte) == 0UL) { + if ((iopte + (1 << cnum)) >= limit) + ent = 0; + else + ent = ent + 1; + iommu->alloc_info[cnum].next = ent; + if (ent == flush_point) + __iommu_flushall(iommu); + break; + } + iopte += (1 << cnum); + ent++; + if (iopte >= limit) { + iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES)); + ent = 0; + } + if (ent == flush_point) + __iommu_flushall(iommu); } /* I've got your streaming cluster right here buddy boy... */ @@ -208,8 +185,15 @@ static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum); iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); iopte_val(*iopte) = 0UL; - if (ent < iommu->lowest_free[cnum]) - iommu->lowest_free[cnum] = ent; + + /* If the global flush might not have caught this entry, + * adjust the flush point such that we will flush before + * ever trying to reuse it. + */ +#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y))) + if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush)) + iommu->alloc_info[cnum].flush = ent; +#undef between } /* We allocate consistent mappings from the end of cluster zero. */ @@ -228,8 +212,13 @@ static iopte_t *alloc_consistent_cluster(struct sbus_iommu *iommu, unsigned long if (iopte_val(*iopte) & IOPTE_VALID) break; } - if (tmp == 0) + if (tmp == 0) { + u32 entry = (iopte - iommu->page_table); + + if (entry < iommu->lowest_consistent_map) + iommu->lowest_consistent_map = entry; return iopte; + } } } return NULL; @@ -239,6 +228,20 @@ static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned { iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) { + iopte_t *walk = iopte + npages; + iopte_t *limit; + + limit = iommu->page_table + CLUSTER_NPAGES; + while (walk < limit) { + if (iopte_val(*walk) != 0UL) + break; + walk++; + } + iommu->lowest_consistent_map = + (walk - iommu->page_table); + } + while (npages--) *iopte++ = __iopte(0UL); } @@ -301,6 +304,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add spin_lock_irq(&iommu->lock); free_consistent_cluster(iommu, dvma, npages); + iommu_flush(iommu, dvma, npages); spin_unlock_irq(&iommu->lock); order = get_order(size); @@ -337,7 +341,6 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di phys_base += PAGE_SIZE; } npages = size >> PAGE_SHIFT; - iommu_flush(iommu, dma_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); return (dma_base | offset); @@ -472,7 +475,6 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int di #ifdef VERIFY_SG verify_sglist(sg, nents, iopte, npages); #endif - iommu_flush(iommu, dma_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); return used; @@ -1061,9 +1063,13 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) memset(iommu, 0, sizeof(*iommu)); - /* Make sure DMA address 0 is never returned just to allow catching - of buggy drivers. */ - iommu->lowest_free[0] = 1; + /* We start with no consistent mappings. */ + iommu->lowest_consistent_map = CLUSTER_NPAGES; + + for (i = 0; i < NCLUSTERS; i++) { + iommu->alloc_info[i].flush = 0; + iommu->alloc_info[i].next = 0; + } /* Setup spinlock. */ spin_lock_init(&iommu->lock); @@ -1110,9 +1116,12 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) */ for (i = 0; i < 16; i++) { unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; + unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; dram += (unsigned long)i * 8UL; + tag += (unsigned long)i * 8UL; upa_writeq(0, dram); + upa_writeq(0, tag); } upa_readq(iommu->sbus_control_reg); diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 96360b010..b4ee5625e 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -328,6 +328,7 @@ again: stxa %6, [%0+%8] %3 membar #Sync stxa %%g0, [%7] %3 + membar #Sync mov 0x20, %%g1 ldxa [%%g1] 0x7f, %%g0 membar #Sync" diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index d3f02ae54..1fc0b1ba5 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.133 2000/03/01 02:53:33 davem Exp $ +/* $Id: sys_sparc32.c,v 1.134 2000/03/07 22:27:30 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index d977c7952..9673cdd36 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.39 2000/02/16 07:31:37 davem Exp $ +/* $Id: sys_sunos32.c,v 1.40 2000/03/07 22:27:31 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 68147d4d4..d09ac451b 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.147 2000/03/03 23:48:44 davem Exp $ +/* $Id: init.c,v 1.148 2000/03/07 07:08:31 anton Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -824,7 +824,7 @@ unsigned long __init bootmem_init(void) sp_banks[i].num_bytes; if (cmdline_memory_size) { if (end_of_phys_memory > cmdline_memory_size) { - if (cmdline_memory_size > sp_banks[i].base_addr) { + if (cmdline_memory_size < sp_banks[i].base_addr) { end_of_phys_memory = sp_banks[i-1].base_addr + sp_banks[i-1].num_bytes; diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index e15ef157c..4adaf4077 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.16 2000/01/12 02:59:27 davem Exp $ +/* $Id: fs.c,v 1.17 2000/03/10 04:43:30 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -410,17 +410,10 @@ struct sol_statvfs64 { static int report_statvfs(struct inode *inode, u32 buf) { struct statfs s; - mm_segment_t old_fs = get_fs(); int error; struct sol_statvfs *ss = (struct sol_statvfs *)A(buf); - if (!inode->i_sb) - return -ENODEV; - if (!inode->i_sb->s_op->statfs) - return -ENOSYS; - set_fs (KERNEL_DS); - error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); - set_fs (old_fs); + error = vfs_statfs(inode->i_sb, &s); if (!error) { const char *p = inode->i_sb->s_type->name; int i = 0; @@ -451,17 +444,10 @@ static int report_statvfs(struct inode *inode, u32 buf) static int report_statvfs64(struct inode *inode, u32 buf) { struct statfs s; - mm_segment_t old_fs = get_fs(); int error; struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf); - if (!inode->i_sb) - return -ENODEV; - if (!inode->i_sb->s_op->statfs) - return -ENOSYS; - set_fs (KERNEL_DS); - error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); - set_fs (old_fs); + error = vfs_statfs(inode->i_sb, &s); if (!error) { const char *p = inode->i_sb->s_type->name; int i = 0; |