summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-13 20:55:15 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-13 20:55:15 +0000
commit1471f525455788c20b130690e0f104df451aeb43 (patch)
tree3778beba56558beb9a9548ea5b467e9c44ea966f /arch
parente80d2c5456d30ebba5b0eb8a9d33e17d815d4d83 (diff)
Merge with Linux 2.3.51.
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/config.in2
-rw-r--r--arch/alpha/defconfig4
-rw-r--r--arch/alpha/kernel/osf_sys.c15
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/config.in2
-rw-r--r--arch/i386/config.in8
-rw-r--r--arch/i386/defconfig10
-rw-r--r--arch/i386/kernel/acpi.c75
-rw-r--r--arch/i386/kernel/apm.c6
-rw-r--r--arch/i386/kernel/pci-pc.c23
-rw-r--r--arch/i386/kernel/process.c6
-rw-r--r--arch/ia64/Makefile8
-rw-r--r--arch/ia64/config.in4
-rw-r--r--arch/ia64/dig/iosapic.c146
-rw-r--r--arch/ia64/hp/hpsim_irq.c81
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c4
-rw-r--r--arch/ia64/kernel/Makefile2
-rw-r--r--arch/ia64/kernel/acpi.c16
-rw-r--r--arch/ia64/kernel/efi.c4
-rw-r--r--arch/ia64/kernel/entry.S4
-rw-r--r--arch/ia64/kernel/fw-emu.c18
-rw-r--r--arch/ia64/kernel/gate.S4
-rw-r--r--arch/ia64/kernel/irq.c1291
-rw-r--r--arch/ia64/kernel/irq_default.c30
-rw-r--r--arch/ia64/kernel/irq_ia64.c247
-rw-r--r--arch/ia64/kernel/irq_internal.c63
-rw-r--r--arch/ia64/kernel/irq_lock.c4
-rw-r--r--arch/ia64/kernel/pci.c7
-rw-r--r--arch/ia64/kernel/perfmon.c117
-rw-r--r--arch/ia64/kernel/process.c20
-rw-r--r--arch/ia64/kernel/semaphore.c5
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/time.c32
-rw-r--r--arch/ia64/kernel/traps.c2
-rw-r--r--arch/ia64/lib/copy_page.S26
-rw-r--r--arch/ia64/lib/copy_user.S31
-rw-r--r--arch/ia64/lib/strncpy_from_user.S30
-rw-r--r--arch/ia64/mm/init.c4
-rw-r--r--arch/ia64/mm/tlb.c4
-rw-r--r--arch/mips/config.in4
-rw-r--r--arch/mips/defconfig6
-rw-r--r--arch/mips/defconfig-decstation8
-rw-r--r--arch/mips/defconfig-ip226
-rw-r--r--arch/mips/kernel/sysirix.c95
-rw-r--r--arch/mips64/config.in3
-rw-r--r--arch/mips64/defconfig8
-rw-r--r--arch/mips64/defconfig-ip278
-rw-r--r--arch/mips64/kernel/mips64_ksyms.c6
-rw-r--r--arch/ppc/boot/Makefile1
-rw-r--r--arch/ppc/chrpboot/Makefile1
-rw-r--r--arch/ppc/coffboot/Makefile4
-rw-r--r--arch/ppc/configs/common_defconfig81
-rw-r--r--arch/ppc/defconfig81
-rw-r--r--arch/ppc/kernel/chrp_time.c2
-rw-r--r--arch/ppc/kernel/irq.c2
-rw-r--r--arch/ppc/kernel/open_pic.c4
-rw-r--r--arch/ppc/kernel/prom.c3
-rw-r--r--arch/ppc/mbxboot/Makefile2
-rw-r--r--arch/ppc/treeboot/Makefile5
-rw-r--r--arch/ppc/xmon/xmon.c42
-rw-r--r--arch/sh/config.in2
-rw-r--r--arch/sh/defconfig4
-rw-r--r--arch/sparc/defconfig5
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c8
-rw-r--r--arch/sparc/kernel/sys_sunos.c2
-rw-r--r--arch/sparc/lib/Makefile6
-rw-r--r--arch/sparc/lib/irqlock.S122
-rw-r--r--arch/sparc/mm/init.c8
-rw-r--r--arch/sparc64/Makefile18
-rw-r--r--arch/sparc64/defconfig5
-rw-r--r--arch/sparc64/kernel/pci_iommu.c183
-rw-r--r--arch/sparc64/kernel/pci_psycho.c22
-rw-r--r--arch/sparc64/kernel/pci_sabre.c24
-rw-r--r--arch/sparc64/kernel/sbus.c205
-rw-r--r--arch/sparc64/kernel/smp.c1
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c2
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c2
-rw-r--r--arch/sparc64/mm/init.c4
-rw-r--r--arch/sparc64/solaris/fs.c20
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;