aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel')
-rw-r--r--arch/ia64/sn/kernel/Makefile5
-rw-r--r--arch/ia64/sn/kernel/bte.c321
-rw-r--r--arch/ia64/sn/kernel/iomv.c115
-rw-r--r--arch/ia64/sn/kernel/irq.c328
-rw-r--r--arch/ia64/sn/kernel/llsc4.c1044
-rw-r--r--arch/ia64/sn/kernel/llsc4.h107
-rw-r--r--arch/ia64/sn/kernel/machvec.c31
-rw-r--r--arch/ia64/sn/kernel/mca.c280
-rw-r--r--arch/ia64/sn/kernel/misctest.c371
-rw-r--r--arch/ia64/sn/kernel/probe.c2
-rw-r--r--arch/ia64/sn/kernel/setup.c268
-rw-r--r--arch/ia64/sn/kernel/sn1/Makefile45
-rw-r--r--arch/ia64/sn/kernel/sn1/cache.c81
-rw-r--r--arch/ia64/sn/kernel/sn1/error.c187
-rw-r--r--arch/ia64/sn/kernel/sn1/iomv.c65
-rw-r--r--arch/ia64/sn/kernel/sn1/sn1_smp.c476
-rw-r--r--arch/ia64/sn/kernel/sn1/synergy.c533
-rw-r--r--arch/ia64/sn/kernel/sn2/Makefile3
-rw-r--r--arch/ia64/sn/kernel/sn2/cache.c5
-rw-r--r--arch/ia64/sn/kernel/sn2/io.c9
-rw-r--r--arch/ia64/sn/kernel/sn2/iomv.c71
-rw-r--r--arch/ia64/sn/kernel/sn2/prominfo_proc.c361
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c333
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c52
-rw-r--r--arch/ia64/sn/kernel/sn_asm.S107
-rw-r--r--arch/ia64/sn/kernel/sn_ksyms.c26
-rw-r--r--arch/ia64/sn/kernel/sv.c2
27 files changed, 1039 insertions, 4189 deletions
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 35191abfd28c9..12e488eb044cf 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -9,11 +9,8 @@
EXTRA_CFLAGS := -DLITTLE_ENDIAN
-obj-y := probe.o setup.o sn_asm.o sv.o bte.o iomv.o \
- irq.o mca.o
+obj-y := probe.o setup.o sv.o bte.o irq.o mca.o
obj-$(CONFIG_IA64_SGI_SN2) += sn2/
-obj-$(CONFIG_IA64_SGI_AUTOTEST) += llsc4.o misctest.o
obj-$(CONFIG_IA64_GENERIC) += machvec.o
obj-$(CONFIG_MODULES) += sn_ksyms.o
-obj-$(CONFIG_IA64_SGI_SN_BRT) += bte_regr_test.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 0e592be762ea7..88409fcc4b8cd 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -1,7 +1,7 @@
/*
*
*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -38,124 +38,160 @@
#include <asm/sn/arch.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/pda.h>
-#ifdef CONFIG_IA64_SGI_SN2
#include <asm/sn/sn2/shubio.h>
-#endif
#include <asm/nodedata.h>
#include <linux/bootmem.h>
#include <linux/string.h>
#include <linux/sched.h>
-#include <asm/sn/bte_copy.h>
+#include <asm/sn/bte.h>
-int bte_offsets[] = { IIO_IBLS0, IIO_IBLS1 };
+#ifndef L1_CACHE_MASK
+#define L1_CACHE_MASK (L1_CACHE_BYTES - 1)
+#endif
/*
- * bte_init_node(nodepda, cnode)
+ * The base address of for each set of bte registers.
+ */
+static int bte_offsets[] = { IIO_IBLS0, IIO_IBLS1 };
+
+
+/************************************************************************
+ * Block Transfer Engine copy related functions.
*
- * Initialize the nodepda structure with BTE base addresses and
- * spinlocks.
+ ***********************************************************************/
+
+
+/*
+ * bte_copy(src, dest, len, mode, notification)
+ *
+ * Use the block transfer engine to move kernel memory from src to dest
+ * using the assigned mode.
+ *
+ * Paramaters:
+ * src - physical address of the transfer source.
+ * dest - physical address of the transfer destination.
+ * len - number of bytes to transfer from source to dest.
+ * mode - hardware defined. See reference information
+ * for IBCT0/1 in the SHUB Programmers Reference
+ * notification - kernel virtual address of the notification cache
+ * line. If NULL, the default is used and
+ * the bte_copy is synchronous.
*
- * NOTE: The kernel parameter btetest will cause the initialization
- * code to reserve blocks of physically contiguous memory to be
- * used by the bte test module.
+ * NOTE: This function requires src, dest, and len to
+ * be cacheline aligned.
*/
-void
-bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
+bte_result_t
+bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
{
- int i;
+ int bte_to_use;
+ u64 transfer_size;
+ struct bteinfo_s *bte;
+ bte_result_t bte_status;
+ unsigned long irq_flags;
- /*
- * Indicate that all the block transfer engines on this node
- * are available.
- */
- for (i = 0; i < BTES_PER_NODE; i++) {
-#ifdef CONFIG_IA64_SGI_SN2
- /* >>> Don't know why the 0x1800000L is here. Robin */
- mynodepda->bte_if[i].bte_base_addr =
- (char *)LOCAL_MMR_ADDR(bte_offsets[i] | 0x1800000L);
+ BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n",
+ src, dest, len, mode, notification));
-#elif CONFIG_IA64_SGI_SN1
- mynodepda->bte_if[i].bte_base_addr =
- (char *)LOCAL_HUB_ADDR(bte_offsets[i]);
-#else
-#error BTE Not defined for this hardware platform.
-#endif
+ if (len == 0) {
+ return BTE_SUCCESS;
+ }
+
+ ASSERT(!((len & L1_CACHE_MASK) ||
+ (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK)));
+ ASSERT(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT));
+
+ do {
+ local_irq_save(irq_flags);
+
+ bte_to_use = 0;
+ /* Attempt to lock one of the BTE interfaces. */
+ while ((bte_to_use < BTES_PER_NODE) &&
+ BTE_LOCK_IF_AVAIL(bte_to_use)) {
+ bte_to_use++;
+ }
+
+ if (bte_to_use < BTES_PER_NODE) {
+ break;
+ }
+
+ local_irq_restore(irq_flags);
+
+ if (!(mode & BTE_WACQUIRE)) {
+ return BTEFAIL_NOTAVAIL;
+ }
+
+ /* Wait until a bte is available. */
+ udelay(10);
+ } while (1);
+
+ bte = pda->cpu_bte_if[bte_to_use];
+ BTE_PRINTKV(("Got a lock on bte %d\n", bte_to_use));
- /*
- * Initialize the notification and spinlock
- * so the first transfer can occur.
- */
- mynodepda->bte_if[i].most_rcnt_na =
- &(mynodepda->bte_if[i].notify);
- mynodepda->bte_if[i].notify = 0L;
-#ifdef CONFIG_IA64_SGI_BTE_LOCKING
- spin_lock_init(&mynodepda->bte_if[i].spinlock);
-#endif /* CONFIG_IA64_SGI_BTE_LOCKING */
- mynodepda->bte_if[i].bte_test_buf =
- alloc_bootmem_node(NODE_DATA(cnode), BTE_MAX_XFER);
+ if (notification == NULL) {
+ /* User does not want to be notified. */
+ bte->most_rcnt_na = &bte->notify;
+ } else {
+ bte->most_rcnt_na = notification;
}
-}
+ /* Calculate the number of cache lines to transfer. */
+ transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK);
+ /* Initialize the notification to a known value. */
+ *bte->most_rcnt_na = -1L;
-/*
- * bte_reset_nasid(nasid_t)
- *
- * Does a soft reset of the BTEs on the specified nasid.
- * This is followed by a one-line transfer from each of the
- * virtual interfaces.
- */
-void
-bte_reset_nasid(nasid_t n)
-{
- ii_ibcr_u_t ibcr;
-
- ibcr.ii_ibcr_regval = REMOTE_HUB_L(n, IIO_IBCR);
- ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
- REMOTE_HUB_S(n, IIO_IBCR, ibcr.ii_ibcr_regval);
-
- /* One line transfer on virtual interface 0 */
- REMOTE_HUB_S(n, IIO_IBLS_0, IBLS_BUSY | 1);
- REMOTE_HUB_S(n, IIO_IBSA_0, TO_PHYS(__pa(&nodepda->bte_cleanup)));
- REMOTE_HUB_S(n, IIO_IBDA_0,
- TO_PHYS(__pa(&nodepda->bte_cleanup[4*L1_CACHE_BYTES])));
- REMOTE_HUB_S(n, IIO_IBNA_0,
- TO_PHYS(__pa(&nodepda->bte_cleanup[4*L1_CACHE_BYTES])));
- REMOTE_HUB_S(n, IIO_IBCT_0, BTE_NOTIFY);
- while (REMOTE_HUB_L(n, IIO_IBLS0)) {
- /* >>> Need some way out in case of hang... */
+ /* Set the status reg busy bit and transfer length */
+ BTE_PRINTKV(("IBLS - HUB_S(0x%p, 0x%lx)\n",
+ BTEREG_LNSTAT_ADDR, IBLS_BUSY | transfer_size));
+ HUB_S(BTEREG_LNSTAT_ADDR, (IBLS_BUSY | transfer_size));
+
+ /* Set the source and destination registers */
+ BTE_PRINTKV(("IBSA - HUB_S(0x%p, 0x%lx)\n", BTEREG_SRC_ADDR,
+ (TO_PHYS(src))));
+ HUB_S(BTEREG_SRC_ADDR, (TO_PHYS(src)));
+ BTE_PRINTKV(("IBDA - HUB_S(0x%p, 0x%lx)\n", BTEREG_DEST_ADDR,
+ (TO_PHYS(dest))));
+ HUB_S(BTEREG_DEST_ADDR, (TO_PHYS(dest)));
+
+ /* Set the notification register */
+ BTE_PRINTKV(("IBNA - HUB_S(0x%p, 0x%lx)\n", BTEREG_NOTIF_ADDR,
+ (TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)))));
+ HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))));
+
+
+ /* Initiate the transfer */
+ BTE_PRINTK(("IBCT - HUB_S(0x%p, 0x%lx)\n", BTEREG_CTRL_ADDR,
+ BTE_VALID_MODE(mode)));
+ HUB_S(BTEREG_CTRL_ADDR, BTE_VALID_MODE(mode));
+
+ spin_unlock_irqrestore(&bte->spinlock, irq_flags);
+
+
+ if (notification != NULL) {
+ return BTE_SUCCESS;
}
- /* One line transfer on virtual interface 1 */
- REMOTE_HUB_S(n, IIO_IBLS_1, IBLS_BUSY | 1);
- REMOTE_HUB_S(n, IIO_IBSA_1, TO_PHYS(__pa(nodepda->bte_cleanup)));
- REMOTE_HUB_S(n, IIO_IBDA_1,
- TO_PHYS(__pa(nodepda->bte_cleanup[4 * L1_CACHE_BYTES])));
- REMOTE_HUB_S(n, IIO_IBNA_1,
- TO_PHYS(__pa(nodepda->bte_cleanup[5 * L1_CACHE_BYTES])));
- REMOTE_HUB_S(n, IIO_IBCT_1, BTE_NOTIFY);
- while (REMOTE_HUB_L(n, IIO_IBLS1)) {
- /* >>> Need some way out in case of hang... */
+ while (*bte->most_rcnt_na == -1UL) {
}
-}
-/*
- * bte_init_cpu()
- *
- * Initialize the cpupda structure with pointers to the
- * nodepda bte blocks.
- *
- */
-void
-bte_init_cpu(void)
-{
- pda->cpu_bte_if[0] = &(nodepda->bte_if[1]);
- pda->cpu_bte_if[1] = &(nodepda->bte_if[0]);
+ BTE_PRINTKV((" Delay Done. IBLS = 0x%lx, most_rcnt_na = 0x%lx\n",
+ HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na));
+
+ if (*bte->most_rcnt_na & IBLS_ERROR) {
+ bte_status = *bte->most_rcnt_na & ~IBLS_ERROR;
+ *bte->most_rcnt_na = 0L;
+ } else {
+ bte_status = BTE_SUCCESS;
+ }
+ BTE_PRINTK(("Returning status is 0x%lx and most_rcnt_na is 0x%lx\n",
+ HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na));
+
+ return bte_status;
}
@@ -192,15 +228,11 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
char *bteBlock;
if (len == 0) {
- return (BTE_SUCCESS);
+ return BTE_SUCCESS;
}
-#ifdef CONFIG_IA64_SGI_BTE_LOCKING
-#error bte_unaligned_copy() assumes single BTE selection in bte_copy().
-#else
/* temporary buffer used during unaligned transfers */
- bteBlock = pda->cpu_bte_if[0]->bte_test_buf;
-#endif
+ bteBlock = pda->cpu_bte_if[0]->scratch_buf;
headBcopySrcOffset = src & L1_CACHE_MASK;
destFirstCacheOffset = dest & L1_CACHE_MASK;
@@ -265,15 +297,15 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
headBteLen += footBteLen;
} else if (footBcopyLen > 0) {
rv = bte_copy(footBteSource,
- __pa(bteBlock),
+ ia64_tpa((unsigned long)bteBlock),
footBteLen, mode, NULL);
if (rv != BTE_SUCCESS) {
- return (rv);
+ return rv;
}
memcpy(__va(footBcopyDest),
- (char *)bteBlock, footBcopyLen);
+ (char *) bteBlock, footBcopyLen);
}
} else {
footBcopyLen = 0;
@@ -288,7 +320,7 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
(len - headBcopyLen -
footBcopyLen), mode, NULL);
if (rv != BTE_SUCCESS) {
- return (rv);
+ return rv;
}
}
@@ -315,14 +347,93 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
if (headBcopyLen > 0) {
rv = bte_copy(headBteSource,
- __pa(bteBlock), headBteLen, mode, NULL);
+ ia64_tpa((unsigned long)bteBlock), headBteLen, mode, NULL);
if (rv != BTE_SUCCESS) {
- return (rv);
+ return rv;
}
- memcpy(__va(headBcopyDest), ((char *)bteBlock +
+ memcpy(__va(headBcopyDest), ((char *) bteBlock +
headBcopySrcOffset),
headBcopyLen);
}
- return (BTE_SUCCESS);
+ return BTE_SUCCESS;
+}
+
+
+/************************************************************************
+ * Block Transfer Engine initialization functions.
+ *
+ ***********************************************************************/
+
+
+/*
+ * bte_init_node(nodepda, cnode)
+ *
+ * Initialize the nodepda structure with BTE base addresses and
+ * spinlocks.
+ */
+void
+bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
+{
+ int i;
+
+
+ /*
+ * Indicate that all the block transfer engines on this node
+ * are available.
+ */
+
+ /*
+ * Allocate one bte_recover_t structure per node. It holds
+ * the recovery lock for node. All the bte interface structures
+ * will point at this one bte_recover structure to get the lock.
+ */
+ spin_lock_init(&mynodepda->bte_recovery_lock);
+ init_timer(&mynodepda->bte_recovery_timer);
+ mynodepda->bte_recovery_timer.function = bte_error_handler;
+ mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda;
+
+ for (i = 0; i < BTES_PER_NODE; i++) {
+ /* >>> Don't know why the 0x1800000L is here. Robin */
+ mynodepda->bte_if[i].bte_base_addr =
+ (char *) LOCAL_MMR_ADDR(bte_offsets[i] | 0x1800000L);
+
+ /*
+ * Initialize the notification and spinlock
+ * so the first transfer can occur.
+ */
+ mynodepda->bte_if[i].most_rcnt_na =
+ &(mynodepda->bte_if[i].notify);
+ mynodepda->bte_if[i].notify = 0L;
+ spin_lock_init(&mynodepda->bte_if[i].spinlock);
+
+ mynodepda->bte_if[i].scratch_buf =
+ alloc_bootmem_node(NODE_DATA(cnode), BTE_MAX_XFER);
+ mynodepda->bte_if[i].bte_cnode = cnode;
+ mynodepda->bte_if[i].bte_error_count = 0;
+ mynodepda->bte_if[i].bte_num = i;
+ mynodepda->bte_if[i].cleanup_active = 0;
+ mynodepda->bte_if[i].bh_error = 0;
+ }
+
+}
+
+/*
+ * bte_init_cpu()
+ *
+ * Initialize the cpupda structure with pointers to the
+ * nodepda bte blocks.
+ *
+ */
+void
+bte_init_cpu(void)
+{
+ /* Called by setup.c as each cpu is being added to the nodepda */
+ if (local_node_data->active_cpu_count & 0x1) {
+ pda->cpu_bte_if[0] = &(nodepda->bte_if[0]);
+ pda->cpu_bte_if[1] = &(nodepda->bte_if[1]);
+ } else {
+ pda->cpu_bte_if[0] = &(nodepda->bte_if[1]);
+ pda->cpu_bte_if[1] = &(nodepda->bte_if[0]);
+ }
}
diff --git a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
deleted file mode 100644
index 6d439ee7521eb..0000000000000
--- a/arch/ia64/sn/kernel/iomv.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <asm/io.h>
-#include <linux/module.h>
-
-extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */
-
-/**
- * sn_inb - read a byte from a port
- * @port: port to read from
- *
- * Reads a byte from @port and returns it to the caller.
- */
-unsigned int
-sn_inb (unsigned long port)
-{
- volatile unsigned char *addr = sn_io_addr(port);
- unsigned char ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-/**
- * sn_inw - read a word from a port
- * @port: port to read from
- *
- * Reads a word from @port and returns it to the caller.
- */
-unsigned int
-sn_inw (unsigned long port)
-{
- volatile unsigned short *addr = sn_io_addr(port);
- unsigned short ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-/**
- * sn_inl - read a word from a port
- * @port: port to read from
- *
- * Reads a word from @port and returns it to the caller.
- */
-unsigned int
-sn_inl (unsigned long port)
-{
- volatile unsigned int *addr = sn_io_addr(port);
- unsigned int ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-/**
- * sn_outb - write a byte to a port
- * @port: port to write to
- * @val: value to write
- *
- * Writes @val to @port.
- */
-void
-sn_outb (unsigned char val, unsigned long port)
-{
- volatile unsigned char *addr = sn_io_addr(port);
-
- *addr = val;
-}
-
-/**
- * sn_outw - write a word to a port
- * @port: port to write to
- * @val: value to write
- *
- * Writes @val to @port.
- */
-void
-sn_outw (unsigned short val, unsigned long port)
-{
- volatile unsigned short *addr = sn_io_addr(port);
-
- *addr = val;
-}
-
-/**
- * sn_outl - write a word to a port
- * @port: port to write to
- * @val: value to write
- *
- * Writes @val to @port.
- */
-void
-sn_outl (unsigned int val, unsigned long port)
-{
- volatile unsigned int *addr = sn_io_addr(port);
-
- *addr = val;
-}
-
-EXPORT_SYMBOL(sn_inb);
-EXPORT_SYMBOL(sn_inw);
-EXPORT_SYMBOL(sn_inl);
-EXPORT_SYMBOL(sn_outb);
-EXPORT_SYMBOL(sn_outw);
-EXPORT_SYMBOL(sn_outl);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 4bf411ccae9b6..8d58bfbc7bf91 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -1,7 +1,7 @@
/*
- * Platform dependent support for SGI SN1
+ * Platform dependent support for SGI SN
*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -32,12 +32,12 @@
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/sn/sgi.h>
@@ -49,19 +49,25 @@
#include <asm/sn/pci/bridge.h>
#include <asm/sn/pci/pciio.h>
#include <asm/sn/pci/pciio_private.h>
-#ifdef ajmtestintr
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/pci/pcibr_private.h>
-#endif /* ajmtestintr */
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/io.h>
#include <asm/sn/intr.h>
#include <asm/sn/addrs.h>
#include <asm/sn/driver.h>
#include <asm/sn/arch.h>
-#include <asm/sn/nodepda.h>
+#include <asm/sn/pda.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
int irq_to_bit_pos(int irq);
+static void force_interrupt(int irq);
+extern void pcibr_force_interrupt(pcibr_intr_t intr);
+extern int sn_force_interrupt_flag;
+
+
static unsigned int
sn_startup_irq(unsigned int irq)
@@ -87,49 +93,11 @@ sn_enable_irq(unsigned int irq)
static void
sn_ack_irq(unsigned int irq)
{
-#ifdef CONFIG_IA64_SGI_SN1
- int bit = -1;
- unsigned long long intpend_val;
- int subnode;
-#endif
-#ifdef CONFIG_IA64_SGI_SN2
unsigned long event_occurred, mask = 0;
-#endif
int nasid;
irq = irq & 0xff;
nasid = smp_physical_node_id();
-#ifdef CONFIG_IA64_SGI_SN1
- subnode = cpuid_to_subnode(smp_processor_id());
- if (irq == SGI_UART_IRQ) {
- intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
- if (intpend_val & (1L<<GFX_INTR_A) ) {
- bit = GFX_INTR_A;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if ( intpend_val & (1L<<GFX_INTR_B) ) {
- bit = GFX_INTR_B;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<PG_MIG_INTR) ) {
- bit = PG_MIG_INTR;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<CC_PEND_A)) {
- bit = CC_PEND_A;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<CC_PEND_B)) {
- bit = CC_PEND_B;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- return;
- }
- bit = irq_to_bit_pos(irq);
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
-#endif
-
-#ifdef CONFIG_IA64_SGI_SN2
event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
@@ -144,34 +112,18 @@ sn_ack_irq(unsigned int irq)
mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
}
HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
-#endif
+ __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
}
static void
sn_end_irq(unsigned int irq)
{
-#ifdef CONFIG_IA64_SGI_SN1
- unsigned long long intpend_val, mask = 0x70L;
- int subnode;
-#endif
int nasid;
-#ifdef CONFIG_IA64_SGI_SN2
+ int ivec;
unsigned long event_occurred;
-#endif
- irq = irq & 0xff;
-#ifdef CONFIG_IA64_SGI_SN1
- if (irq == SGI_UART_IRQ) {
- nasid = smp_physical_node_id();
- subnode = cpuid_to_subnode(smp_processor_id());
- intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
- if (intpend_val & mask) {
- platform_send_ipi(smp_processor_id(), SGI_UART_IRQ, IA64_IPI_DM_INT, 0);
- }
- }
-#endif
-#ifdef CONFIG_IA64_SGI_SN2
- if (irq == SGI_UART_VECTOR) {
+ ivec = irq & 0xff;
+ if (ivec == SGI_UART_VECTOR) {
nasid = smp_physical_node_id();
event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
// If the UART bit is set here, we may have received an interrupt from the
@@ -181,8 +133,9 @@ sn_end_irq(unsigned int irq)
platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
}
}
-#endif
-
+ __clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
+ if (sn_force_interrupt_flag)
+ force_interrupt(irq);
}
static void
@@ -191,7 +144,7 @@ sn_set_affinity_irq(unsigned int irq, unsigned long mask)
}
-struct hw_interrupt_type irq_type_iosapic_level = {
+struct hw_interrupt_type irq_type_sn = {
"SN hub",
sn_startup_irq,
sn_shutdown_irq,
@@ -203,29 +156,17 @@ struct hw_interrupt_type irq_type_iosapic_level = {
};
-#define irq_type_sn irq_type_iosapic_level
-struct irq_desc *_sn_irq_desc[NR_CPUS];
-
struct irq_desc *
sn_irq_desc(unsigned int irq) {
- int cpu = irq >> 8;
- irq = irq & 0xff;
+ irq = SN_IVEC_FROM_IRQ(irq);
- return(_sn_irq_desc[cpu] + irq);
+ return(_irq_desc + irq);
}
u8
sn_irq_to_vector(u8 irq) {
- return(irq & 0xff);
-}
-
-int gsi_to_vector(u32 irq) {
- return irq & 0xff;
-}
-
-int gsi_to_irq(u32 irq) {
- return irq & 0xff;
+ return(irq);
}
unsigned int
@@ -233,47 +174,24 @@ sn_local_vector_to_irq(u8 vector) {
return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
}
-void *kmalloc(size_t, int);
-
void
sn_irq_init (void)
{
int i;
irq_desc_t *base_desc = _irq_desc;
- for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IVECS; i++) {
+ for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IRQS; i++) {
if (base_desc[i].handler == &no_irq_type) {
base_desc[i].handler = &irq_type_sn;
}
}
}
-void
-sn_init_irq_desc(void) {
- int i;
- irq_desc_t *base_desc = _irq_desc, *p;
-
- for (i=0; i < NR_CPUS; i++) {
- p = page_address(alloc_pages_node(local_nodeid, GFP_KERNEL,
- get_order(sizeof(struct irq_desc) * NR_IVECS) ) );
- ASSERT(p);
- memcpy(p, base_desc, sizeof(struct irq_desc) * NR_IVECS);
- _sn_irq_desc[i] = p;
- }
-}
-
-
int
bit_pos_to_irq(int bit) {
#define BIT_TO_IRQ 64
if (bit > 118) bit = 118;
-#ifdef CONFIG_IA64_SGI_SN1
- if (bit >= GFX_INTR_A && bit <= CC_PEND_B) {
- return SGI_UART_IRQ;
- }
-#endif
-
return bit + BIT_TO_IRQ;
}
@@ -285,53 +203,181 @@ irq_to_bit_pos(int irq) {
return bit;
}
-#ifdef ajmtestintr
-
-#include <linux/timer.h>
-struct timer_list intr_test_timer = TIMER_INITIALIZER(NULL, 0, 0);
-int intr_test_icount[NR_IRQS];
-struct intr_test_reg_struct {
- pcibr_soft_t pcibr_soft;
- int slot;
+struct pcibr_intr_list_t {
+ struct pcibr_intr_list_t *next;
+ pcibr_intr_t intr;
};
-struct intr_test_reg_struct intr_test_registered[NR_IRQS];
+
+static struct pcibr_intr_list_t **pcibr_intr_list;
void
-intr_test_handle_timer(unsigned long data) {
+register_pcibr_intr(int irq, pcibr_intr_t intr) {
+ struct pcibr_intr_list_t *p = kmalloc(sizeof(struct pcibr_intr_list_t), GFP_KERNEL);
+ struct pcibr_intr_list_t *list;
+ int cpu = SN_CPU_FROM_IRQ(irq);
+
+ if (pcibr_intr_list == NULL) {
+ pcibr_intr_list = kmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS, GFP_KERNEL);
+ if (pcibr_intr_list == NULL) panic("Could not allocate memory for pcibr_intr_list\n");
+ memset( (void *)pcibr_intr_list, 0, sizeof(struct pcibr_intr_list_t *) * NR_IRQS);
+ }
+ if (pdacpu(cpu)->sn_last_irq < irq) {
+ pdacpu(cpu)->sn_last_irq = irq;
+ }
+ if (pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq;
+ if (!p) panic("Could not allocate memory for pcibr_intr_list_t\n");
+ if ((list = pcibr_intr_list[irq])) {
+ while (list->next) list = list->next;
+ list->next = p;
+ p->next = NULL;
+ p->intr = intr;
+ } else {
+ pcibr_intr_list[irq] = p;
+ p->next = NULL;
+ p->intr = intr;
+ }
+}
+
+void
+force_polled_int(void) {
int i;
- bridge_t *bridge;
-
- for (i=0;i<NR_IRQS;i++) {
- if (intr_test_registered[i].pcibr_soft) {
- pcibr_soft_t pcibr_soft = intr_test_registered[i].pcibr_soft;
- xtalk_intr_t intr = pcibr_soft->bs_intr[intr_test_registered[i].slot].bsi_xtalk_intr;
- /* send interrupt */
- bridge = pcibr_soft->bs_base;
- bridge->b_force_always[intr_test_registered[i].slot].intr = 1;
+ struct pcibr_intr_list_t *p;
+
+ for (i=0; i<NR_IRQS;i++) {
+ p = pcibr_intr_list[i];
+ while (p) {
+ if (p->intr){
+ pcibr_force_interrupt(p->intr);
+ }
+ p = p->next;
}
}
- del_timer(&intr_test_timer);
- intr_test_timer.expires = jiffies + HZ/100;
- add_timer(&intr_test_timer);
}
-void
-intr_test_set_timer(void) {
- intr_test_timer.expires = jiffies + HZ/100;
- intr_test_timer.function = intr_test_handle_timer;
- add_timer(&intr_test_timer);
+static void
+force_interrupt(int irq) {
+ struct pcibr_intr_list_t *p = pcibr_intr_list[irq];
+
+ while (p) {
+ if (p->intr) {
+ pcibr_force_interrupt(p->intr);
+ }
+ p = p->next;
+ }
+}
+
+/*
+Check for lost interrupts. If the PIC int_status reg. says that
+an interrupt has been sent, but not handled, and the interrupt
+is not pending in either the cpu irr regs or in the soft irr regs,
+and the interrupt is not in service, then the interrupt may have
+been lost. Force an interrupt on that pin. It is possible that
+the interrupt is in flight, so we may generate a spurious interrupt,
+but we should never miss a real lost interrupt.
+*/
+
+static void
+sn_check_intr(int irq, pcibr_intr_t intr) {
+ unsigned long regval;
+ int irr_reg_num;
+ int irr_bit;
+ unsigned long irr_reg;
+
+
+ regval = intr->bi_soft->bs_base->p_int_status_64;
+ irr_reg_num = irq_to_vector(irq) / 64;
+ irr_bit = irq_to_vector(irq) % 64;
+ switch (irr_reg_num) {
+ case 0:
+ irr_reg = ia64_get_irr0();
+ break;
+ case 1:
+ irr_reg = ia64_get_irr1();
+ break;
+ case 2:
+ irr_reg = ia64_get_irr2();
+ break;
+ case 3:
+ irr_reg = ia64_get_irr3();
+ break;
+ }
+ if (!test_bit(irr_bit, &irr_reg) ) {
+ if (!test_bit(irq, pda->sn_soft_irr) ) {
+ if (!test_bit(irq, pda->sn_in_service_ivecs) ) {
+ regval &= 0xff;
+ if (intr->bi_ibits & regval & intr->bi_last_intr) {
+ regval &= ~(intr->bi_ibits & regval);
+ pcibr_force_interrupt(intr);
+ }
+ }
+ }
+ }
+ intr->bi_last_intr = regval;
}
void
-intr_test_register_irq(int irq, pcibr_soft_t pcibr_soft, int slot) {
- irq = irq & 0xff;
- intr_test_registered[irq].pcibr_soft = pcibr_soft;
- intr_test_registered[irq].slot = slot;
+sn_lb_int_war_check(void) {
+ int i;
+
+ if (pda->sn_first_irq == 0) return;
+ for (i=pda->sn_first_irq;
+ i <= pda->sn_last_irq; i++) {
+ struct pcibr_intr_list_t *p = pcibr_intr_list[i];
+ if (p == NULL) {
+ continue;
+ }
+ while (p) {
+ sn_check_intr(i, p->intr);
+ p = p->next;
+ }
+ }
+}
+
+static inline int
+sn_get_next_bit(void) {
+ int i;
+ int bit;
+
+ for (i = 3; i >= 0; i--) {
+ if (pda->sn_soft_irr[i] != 0) {
+ bit = (i * 64) + __ffs(pda->sn_soft_irr[i]);
+ __change_bit(bit, (volatile void *)pda->sn_soft_irr);
+ return(bit);
+ }
+ }
+ return IA64_SPURIOUS_INT_VECTOR;
}
void
-intr_test_handle_intr(int irq, void *junk, struct pt_regs *morejunk) {
- intr_test_icount[irq]++;
- printk("RECEIVED %d INTERRUPTS ON IRQ %d\n",intr_test_icount[irq], irq);
+sn_set_tpr(int vector) {
+ if (vector > IA64_LAST_DEVICE_VECTOR || vector < IA64_FIRST_DEVICE_VECTOR) {
+ ia64_set_tpr(vector);
+ } else {
+ ia64_set_tpr(IA64_LAST_DEVICE_VECTOR);
+ }
+}
+
+static inline void
+sn_get_all_ivr(void) {
+ int vector;
+
+ vector = ia64_get_ivr();
+ while (vector != IA64_SPURIOUS_INT_VECTOR) {
+ __set_bit(vector, (volatile void *)pda->sn_soft_irr);
+ ia64_eoi();
+ if (vector > IA64_LAST_DEVICE_VECTOR) return;
+ vector = ia64_get_ivr();
+ }
+}
+
+int
+sn_get_ivr(void) {
+ int vector;
+
+ vector = sn_get_next_bit();
+ if (vector == IA64_SPURIOUS_INT_VECTOR) {
+ sn_get_all_ivr();
+ vector = sn_get_next_bit();
+ }
+ return vector;
}
-#endif /* ajmtestintr */
diff --git a/arch/ia64/sn/kernel/llsc4.c b/arch/ia64/sn/kernel/llsc4.c
deleted file mode 100644
index 38373739789d6..0000000000000
--- a/arch/ia64/sn/kernel/llsc4.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-#include <linux/kernel_stat.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/efi.h>
-#include <asm/page.h>
-#include <linux/threads.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/leds.h>
-
-#include "llsc4.h"
-
-
-#ifdef STANDALONE
-#include "lock.h"
-#endif
-
-#ifdef INTTEST
-static int inttest=0;
-#endif
-
-#ifdef IA64_SEMFIX_INSN
-#undef IA64_SEMFIX_INSN
-#endif
-#ifdef IA64_SEMFIX
-#undef IA64_SEMFIX
-#endif
-# define IA64_SEMFIX_INSN
-# define IA64_SEMFIX ""
-
-#define NOLOCK 0xdead
-#define BGUARD(linei) (0xbbbb0000 | (linei));
-#define EGUARD(linei) (0xeeee0000 | (linei));
-#define GUARDLINE(v) ((v)&0xffff)
-
-/*
- * Test parameter table for AUTOTEST
- */
-typedef struct {
- int passes;
- int linecount;
- int linepad;
-} autotest_table_t;
-
-autotest_table_t autotest_table[] = {
- {50000000, 2, 0x2b4 },
- {50000000, 16, 0, },
- {50000000, 16, 4, },
- {50000000, 128, 0x44 },
- {50000000, 128, 0x84 },
- {50000000, 128, 0x200 },
- {50000000, 128, 0x204 },
- {50000000, 128, 0x2b4 },
- {50000000, 2, 8*MB+0x2b4 },
- {50000000, 16, 8*MB+0 },
- {50000000, 16, 8*MB+4 },
- {50000000, 128, 8*MB+0x44 },
- {50000000, 128, 8*MB+0x84 },
- {50000000, 128, 8*MB+0x200 },
- {50000000, 128, 8*MB+0x204 },
- {50000000, 128, 8*MB+0x2b4 },
- {0}};
-
-/*
- * Array of virtual addresses available for test purposes.
- */
-
-typedef struct {
- long vstart;
- long vend;
- long nextaddr;
- long nextinit;
- int wrapcount;
-} memmap_t;
-
-#define MAPCHUNKS 128
-memmap_t memmap[MAPCHUNKS];
-int memmapx=0;
-
-typedef struct {
- void *addr;
- long data[16];
- long data_fc[16];
-} capture_line_t;
-
-typedef struct {
- int size;
- void *blockaddr;
- void *shadaddr;
- long blockdata[48];
- long shaddata[48];
- long blockdata_fc[48];
- long shaddata_fc[48];
- long synerr;
-} capture_t;
-
-/*
- * PORTING NOTE: revisit this statement. On hardware we put mbase at 0 and
- * the rest of the tables have to start at 1MB to skip PROM tables.
- */
-#define THREADPRIVATESZ() ((sizeof(threadprivate_t)+511)/512*512)
-#define THREADPRIVATE(t) ((threadprivate_t*)(((long)mbase)+4096+t*THREADPRIVATESZ()))
-
-#define k_capture mbase->sk_capture
-#define k_go mbase->sk_go
-#define k_linecount mbase->sk_linecount
-#define k_passes mbase->sk_passes
-#define k_napticks mbase->sk_napticks
-#define k_stop_on_error mbase->sk_stop_on_error
-#define k_verbose mbase->sk_verbose
-#define k_threadprivate mbase->sk_threadprivate
-#define k_blocks mbase->sk_blocks
-#define k_iter_msg mbase->sk_iter_msg
-#define k_vv mbase->sk_vv
-#define k_linepad mbase->sk_linepad
-#define k_options mbase->sk_options
-#define k_testnumber mbase->sk_testnumber
-#define k_currentpass mbase->sk_currentpass
-
-static long blocks[MAX_LINECOUNT]; /* addresses of data blocks */
-static control_t *mbase;
-static vint initialized=0;
-
-static unsigned int ran_conf_llsc(int);
-static int rerr(capture_t *, char *, void *, void *, int, int, int, int, int, int);
-static void dumpline(void *, char *, char *, void *, void *, int);
-static int checkstop(int, int, uint);
-static void spin(int);
-static void capturedata(capture_t *, uint, void *, void *, int);
-static int randn(uint max, uint *seed);
-static uint zrandom (uint *zranseed);
-static int set_lock(uint *, uint);
-static int clr_lock(uint *, uint);
-static void Speedo(void);
-
-int autotest_enabled=0;
-static int llsctest_number=-1;
-static int errstop_enabled=0;
-static int fail_enabled=0;
-static int l4_opt=0;
-static int selective_trigger=0;
-static int dump_block_addrs_opt=0;
-static lock_t errlock=NOLOCK;
-static private_t init_private[LLSC_MAXCPUS];
-
-static int __init autotest_enable(char *str)
-{
- autotest_enabled = 1;
- return 1;
-}
-static int __init set_llscblkadr(char *str)
-{
- dump_block_addrs_opt = 1;
- return 1;
-}
-static int __init set_llscselt(char *str)
-{
- selective_trigger = 1;
- return 1;
-}
-static int __init set_llsctest(char *str)
-{
- llsctest_number = simple_strtol(str, &str, 10);
- if (llsctest_number < 0 || llsctest_number > 15)
- llsctest_number = -1;
- return 1;
-}
-static int __init set_llscerrstop(char *str)
-{
- errstop_enabled = 1;
- return 1;
-}
-static int __init set_llscfail(char *str)
-{
- fail_enabled = 8;
- return 1;
-}
-static int __init set_llscl4(char *str)
-{
- l4_opt = 1;
- return 1;
-}
-
-static void print_params(void)
-{
- printk ("********* Enter AUTOTEST facility on master cpu *************\n");
- printk (" Test options:\n");
- printk (" llsctest=<n>\t%d\tTest number to run (all = -1)\n", llsctest_number);
- printk (" llscerrstop \t%s\tStop on error\n", errstop_enabled ? "on" : "off");
- printk (" llscfail \t%s\tForce a failure to test the trigger & error messages\n", fail_enabled ? "on" : "off");
- printk (" llscselt \t%s\tSelective triger on failures\n", selective_trigger ? "on" : "off");
- printk (" llscblkadr \t%s\tDump data block addresses\n", dump_block_addrs_opt ? "on" : "off");
- printk (" llscl4 \t%s\tRun only tests that evict from L4\n", l4_opt ? "on" : "off");
- printk (" SEMFIX: %s\n", IA64_SEMFIX);
- printk ("\n");
-}
-__setup("autotest", autotest_enable);
-__setup("llsctest=", set_llsctest);
-__setup("llscerrstop", set_llscerrstop);
-__setup("llscfail", set_llscfail);
-__setup("llscselt", set_llscselt);
-__setup("llscblkadr", set_llscblkadr);
-__setup("llscl4", set_llscl4);
-
-
-
-static inline int
-set_lock(uint *lock, uint id)
-{
- uint old;
- old = cmpxchg_acq(lock, NOLOCK, id);
- return (old == NOLOCK);
-}
-
-static inline int
-clr_lock(uint *lock, uint id)
-{
- uint old;
- old = cmpxchg_rel(lock, id, NOLOCK);
- return (old == id);
-}
-
-static inline void
-init_lock(uint *lock)
-{
- *lock = NOLOCK;
-}
-
-/*------------------------------------------------------------------------+
-| Routine : ran_conf_llsc - ll/sc shared data test |
-| Description: This test checks the coherency of shared data |
-+------------------------------------------------------------------------*/
-static unsigned int
-ran_conf_llsc(int thread)
-{
- private_t pval;
- share_t sval, sval2;
- uint vv, linei, slinei, sharei, pass;
- long t;
- lock_t lockpat;
- share_t *sharecopy;
- long verbose, napticks, passes, linecount, lcount;
- dataline_t *linep, *slinep;
- int s, seed;
- threadprivate_t *tp;
- uint iter_msg, iter_msg_i=0;
- int vv_mask;
- int correct_errors;
- int errs=0;
- int stillbad;
- capture_t capdata;
- private_t *privp;
- share_t *sharep;
-
-
- linecount = k_linecount;
- napticks = k_napticks;
- verbose = k_verbose;
- passes = k_passes;
- iter_msg = k_iter_msg;
- seed = (thread + 1) * 647;
- tp = THREADPRIVATE(thread);
- vv_mask = (k_vv>>((thread%16)*4)) & 0xf;
- correct_errors = k_options&0xff;
-
- memset (&capdata, 0, sizeof(capdata));
- for (linei=0; linei<linecount; linei++)
- tp->private[linei] = thread;
-
- for (pass = 1; passes == 0 || pass < passes; pass++) {
- lockpat = (pass & 0x0fffffff) + (thread <<28);
- if (lockpat == NOLOCK)
- continue;
- tp->threadpasses = pass;
- if (checkstop(thread, pass, lockpat))
- return 0;
- iter_msg_i++;
- if (iter_msg && iter_msg_i > iter_msg) {
- printk("Thread %d, Pass %d\n", thread, pass);
- iter_msg_i = 0;
- }
- lcount = 0;
-
- /*
- * Select line to perform operations on.
- */
- linei = randn(linecount, &seed);
- sharei = randn(2, &seed);
- slinei = (linei + (linecount/2))%linecount; /* I don't like this - fix later */
-
- linep = (dataline_t *)blocks[linei];
- slinep = (dataline_t *)blocks[slinei];
- if (sharei == 0)
- sharecopy = &slinep->share0;
- else
- sharecopy = &slinep->share1;
-
-
- vv = randn(4, &seed);
- if ((vv_mask & (1<<vv)) == 0)
- continue;
-
- if (napticks) {
- t = randn(napticks, &seed);
- udelay(t);
- }
- privp = &linep->private[thread];
- sharep = &linep->share[sharei];
-
- switch(vv) {
- case 0:
- /* Read and verify private count on line. */
- pval = *privp;
- if (verbose)
- printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]);
- if (pval != tp->private[linei]) {
- capturedata(&capdata, pass, privp, NULL, sizeof(*privp));
- stillbad = (*privp != tp->private[linei]);
- if (rerr(&capdata, "Private count", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) {
- return 1;
- }
- if (correct_errors) {
- tp->private[linei] = *privp;
- }
- errs++;
- }
- break;
-
- case 1:
- /* Read, verify, and increment private count on line. */
- pval = *privp;
- if (verbose)
- printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]);
- if (pval != tp->private[linei]) {
- capturedata(&capdata, pass, privp, NULL, sizeof(*privp));
- stillbad = (*privp != tp->private[linei]);
- if (rerr(&capdata, "Private count & inc", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) {
- return 1;
- }
- errs++;
- }
- pval = (pval==255) ? 0 : pval+1;
- *privp = pval;
- tp->private[linei] = pval;
- break;
-
- case 2:
- /* Lock line, read and verify shared data. */
- if (verbose)
- printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy);
- lcount = 0;
- while (LOCK(sharei) != 1) {
- if (checkstop(thread, pass, lockpat))
- return 0;
- if (lcount++>1000000) {
- capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t));
- stillbad = (GETLOCK(sharei) != 0);
- rerr(&capdata, "Shared data lock", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad);
- return 1;
- }
- if ((lcount&0x3fff) == 0)
- udelay(1000);
- }
-
- sval = *sharep;
- sval2 = *sharecopy;
- if (pass > 12 && thread == 0 && fail_enabled == 1)
- sval++;
- if (sval != sval2) {
- capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy));
- stillbad = (*sharep != *sharecopy);
- if (!stillbad && *sharep != sval && *sharecopy == sval2)
- stillbad = 2;
- if (rerr(&capdata, "Shared data", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) {
- return 1;
- }
- if (correct_errors)
- *sharep = *sharecopy;
- errs++;
- }
-
-
- if ( (s=UNLOCK(sharei)) != 1) {
- capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4);
- stillbad = (GETLOCK(sharei) != lockpat);
- if (rerr(&capdata, "Shared data unlock", linep, slinep, thread, pass, linei, lockpat, GETLOCK(sharei), stillbad))
- return 1;
- if (correct_errors)
- ZEROLOCK(sharei);
- errs++;
- }
- break;
-
- case 3:
- /* Lock line, read and verify shared data, modify shared data. */
- if (verbose)
- printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy);
- lcount = 0;
- while (LOCK(sharei) != 1) {
- if (checkstop(thread, pass, lockpat))
- return 0;
- if (lcount++>1000000) {
- capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t));
- stillbad = (GETLOCK(sharei) != 0);
- rerr(&capdata, "Shared data lock & inc", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad);
- return 1;
- }
- if ((lcount&0x3fff) == 0)
- udelay(1000);
- }
- sval = *sharep;
- sval2 = *sharecopy;
- if (sval != sval2) {
- capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy));
- stillbad = (*sharep != *sharecopy);
- if (!stillbad && *sharep != sval && *sharecopy == sval2)
- stillbad = 2;
- if (rerr(&capdata, "Shared data & inc", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) {
- return 1;
- }
- errs++;
- }
-
- *sharep = lockpat;
- *sharecopy = lockpat;
-
-
- if ( (s=UNLOCK(sharei)) != 1) {
- capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4);
- stillbad = (GETLOCK(sharei) != lockpat);
- if (rerr(&capdata, "Shared data & inc unlock", linep, slinep, thread, pass, linei, thread, GETLOCK(sharei), stillbad))
- return 1;
- if (correct_errors)
- ZEROLOCK(sharei);
- errs++;
- }
- break;
- }
- }
-
- return (errs > 0);
-}
-
-static void
-trigger_la(long val)
-{
- long *p;
-
- p = (long*)0xc0000a0001000020L; /* PI_CPU_NUM */
- *p = val;
-}
-
-static long
-getsynerr(void)
-{
- long err, *errp;
-
- errp = (long*)0xc0000e0000000340L; /* SYN_ERR */
- err = *errp;
- if (err)
- *errp = -1L;
- return (err & ~0x60);
-}
-
-static int
-rerr(capture_t *cap, char *msg, void *lp, void *slp, int thread, int pass, int badlinei, int exp, int found, int stillbad)
-{
- int cpu, i, linei;
- long synerr;
- int selt;
-
-
- selt = selective_trigger && stillbad > 1 &&
- memcmp(cap->blockdata, cap->blockdata_fc, 128) != 0 &&
- memcmp(cap->shaddata, cap->shaddata_fc, 128) == 0;
- if (selt) {
- trigger_la(pass);
- } else if (selective_trigger) {
- k_go = ST_STOP;
- return k_stop_on_error;;
- }
-
- spin(1);
- i = 100;
- while (i && set_lock(&errlock, 1) != 1) {
- spin(1);
- i--;
- }
- printk ("\nDataError!: %-20s, test %ld, thread %d, line:%d, pass %d (0x%x), time %ld expected:%x, found:%x\n",
- msg, k_testnumber, thread, badlinei, pass, pass, jiffies, exp, found);
-
- dumpline (lp, "Corrupted data", "D ", cap->blockaddr, cap->blockdata, cap->size);
-#ifdef ZZZ
- if (memcmp(cap->blockdata, cap->blockdata_fc, 128))
- dumpline (lp, "Corrupted data", "DF", cap->blockaddr, cap->blockdata_fc, cap->size);
-#endif
-
- if (cap->shadaddr) {
- dumpline (slp, "Shadow data", "S ", cap->shadaddr, cap->shaddata, cap->size);
-#ifdef ZZZ
- if (memcmp(cap->shaddata, cap->shaddata_fc, 128))
- dumpline (slp, "Shadow data", "SF", cap->shadaddr, cap->shaddata_fc, cap->size);
-#endif
- }
-
- printk("Threadpasses: ");
- for (cpu=0,i=0; cpu<LLSC_MAXCPUS; cpu++)
- if (k_threadprivate[cpu]->threadpasses) {
- if (i && (i%8) == 0)
- printk("\n : ");
- printk(" %d:0x%x", cpu, k_threadprivate[cpu]->threadpasses);
- i++;
- }
- printk("\n");
-
- for (linei=0; linei<k_linecount; linei++) {
- int slinei, g1linei, g2linei, g1err, g2err, sh0err, sh1err;
- dataline_t *linep, *slinep;
-
- slinei = (linei + (k_linecount/2))%k_linecount;
- linep = (dataline_t *)blocks[linei];
- slinep = (dataline_t *)blocks[slinei];
-
- g1linei = GUARDLINE(linep->guard1);
- g2linei = GUARDLINE(linep->guard2);
- g1err = (g1linei != linei);
- g2err = (g2linei != linei);
- sh0err = (linep->share[0] != slinep->share0);
- sh1err = (linep->share[1] != slinep->share1);
-
- if (g1err || g2err || sh0err || sh1err) {
- printk("Line 0x%lx (%03d), %sG1 0x%lx (%03d), %sG2 0x%lx (%03d), %sSH0 %08x (%08x), %sSH1 %08x (%08x)\n",
- blocks[linei], linei,
- g1err ? "*" : " ", blocks[g1linei], g1linei,
- g2err ? "*" : " ", blocks[g2linei], g2linei,
- sh0err ? "*" : " ", linep->share[0], slinep->share0,
- sh1err ? "*" : " ", linep->share[1], slinep->share1);
-
-
- }
- }
-
- printk("\nData was %sfixed by flushcache\n", (stillbad == 1 ? "**** NOT **** " : " "));
- synerr = getsynerr();
- if (synerr)
- printk("SYNERR: Thread %d, Synerr: 0x%lx\n", thread, synerr);
- spin(2);
- printk("\n\n");
- clr_lock(&errlock, 1);
-
- if (errstop_enabled) {
- local_irq_disable();
- while(1);
- }
- return k_stop_on_error;
-}
-
-
-static void
-dumpline(void *lp, char *str1, char *str2, void *addr, void *data, int size)
-{
- long *p;
- int i, off;
-
- printk("%s at 0x%lx, size %d, block starts at 0x%lx\n", str1, (long)addr, size, (long)lp);
- p = (long*) data;
- for (i=0; i<48; i++, p++) {
- if (i%8 == 0) printk("%2s", i==16 ? str2 : " ");
- printk(" %016lx", *p);
- if ((i&7)==7) printk("\n");
- }
- printk(" ");
- off = (((long)addr) ^ size) & 63L;
- for (i=0; i<off+size; i++) {
- printk("%s", (i>=off) ? "--" : " ");
- if ((i%8) == 7)
- printk(" ");
- }
-
- off = ((long)addr) & 127;
- printk(" (line %d)\n", 2+off/64+1);
-}
-
-
-static int
-randn(uint max, uint *seedp)
-{
- if (max == 1)
- return(0);
- else
- return((int)(zrandom(seedp)>>10) % max);
-}
-
-
-static int
-checkstop(int thread, int pass, uint lockpat)
-{
- long synerr;
-
- if (k_go == ST_RUN)
- return 0;
- if (k_go == ST_STOP)
- return 1;
-
- if (errstop_enabled) {
- local_irq_disable();
- while(1);
- }
- synerr = getsynerr();
- spin(2);
- if (k_go == ST_STOP)
- return 1;
- if (synerr)
- printk("SYNERR: Thread %d, Synerr: 0x%lx\n", thread, synerr);
- return 1;
-}
-
-
-static void
-spin(int j)
-{
- udelay(j * 500000);
-}
-
-static void
-capturedata(capture_t *cap, uint pass, void *blockaddr, void *shadaddr, int size)
-{
-
- if (!selective_trigger)
- trigger_la (pass);
-
- memcpy (cap->blockdata, CACHEALIGN(blockaddr)-128, 3*128);
- if (shadaddr)
- memcpy (cap->shaddata, CACHEALIGN(shadaddr)-128, 3*128);
-
- if (k_stop_on_error) {
- k_go = ST_ERRSTOP;
- }
-
- cap->size = size;
- cap->blockaddr = blockaddr;
- cap->shadaddr = shadaddr;
-
- asm volatile ("fc %0" :: "r"(blockaddr) : "memory");
- ia64_sync_i();
- ia64_srlz_d();
- memcpy (cap->blockdata_fc, CACHEALIGN(blockaddr)-128, 3*128);
-
- if (shadaddr) {
- asm volatile ("fc %0" :: "r"(shadaddr) : "memory");
- ia64_sync_i();
- ia64_srlz_d();
- memcpy (cap->shaddata_fc, CACHEALIGN(shadaddr)-128, 3*128);
- }
-}
-
-int zranmult = 0x48c27395;
-
-static uint
-zrandom (uint *seedp)
-{
- *seedp = (*seedp * zranmult) & 0x7fffffff;
- return (*seedp);
-}
-
-
-void
-set_autotest_params(void)
-{
- static int testnumber=-1;
-
- if (llsctest_number >= 0) {
- testnumber = llsctest_number;
- } else {
- testnumber++;
- if (autotest_table[testnumber].passes == 0) {
- testnumber = 0;
- dump_block_addrs_opt = 0;
- }
- }
- if (testnumber == 0 && l4_opt) testnumber = 9;
-
- k_passes = autotest_table[testnumber].passes;
- k_linepad = autotest_table[testnumber].linepad;
- k_linecount = autotest_table[testnumber].linecount;
- k_testnumber = testnumber;
-
- if (IS_RUNNING_ON_SIMULATOR()) {
- printk ("llsc start test %ld\n", k_testnumber);
- k_passes = 1000;
- }
-}
-
-
-static void
-set_leds(int errs)
-{
- unsigned char leds=0;
-
- /*
- * Leds are:
- * ppppeee-
- * where
- * pppp = test number
- * eee = error count but top bit is stick
- */
-
- leds = ((errs&7)<<1) | ((k_testnumber&15)<<4) | (errs ? 0x08 : 0);
- set_led_bits(leds, LED_MASK_AUTOTEST);
-}
-
-static void
-setup_block_addresses(void)
-{
- int i, stride, memmapi;
- dataline_t *dp;
- long *ip, *ipe;
-
-
- stride = k_linepad + sizeof(dataline_t);
- memmapi = 0;
- for (i=0; i<memmapx; i++) {
- memmap[i].nextaddr = memmap[i].vstart;
- memmap[i].nextinit = memmap[i].vstart;
- memmap[i].wrapcount = 0;
- }
-
- for (i=0; i<k_linecount; i++) {
- blocks[i] = memmap[memmapi].nextaddr;
- dp = (dataline_t*)blocks[i];
- memmap[memmapi].nextaddr += (stride & 0xffff);
- if (memmap[memmapi].nextaddr + sizeof(dataline_t) >= memmap[memmapi].vend) {
- memmap[memmapi].wrapcount++;
- memmap[memmapi].nextaddr = memmap[memmapi].vstart +
- memmap[memmapi].wrapcount * sizeof(dataline_t);
- }
-
- ip = (long*)((memmap[memmapi].nextinit+7)&~7);
- ipe = (long*)(memmap[memmapi].nextaddr+2*sizeof(dataline_t)+8);
- while(ip <= ipe && ip < ((long*)memmap[memmapi].vend-8))
- *ip++ = (long)ip;
- memmap[memmapi].nextinit = (long) ipe;
- dp->guard1 = BGUARD(i);
- dp->guard2 = EGUARD(i);
- dp->lock[0] = dp->lock[1] = NOLOCK;
- dp->share[0] = dp->share0 = 0x1111;
- dp->share[1] = dp->share1 = 0x2222;
- memcpy(dp->private, init_private, LLSC_MAXCPUS*sizeof(private_t));
-
-
- if (stride > 16384) {
- memmapi++;
- if (memmapi == memmapx)
- memmapi = 0;
- }
- }
-
-}
-
-static void
-dump_block_addrs(void)
-{
- int i;
-
- printk("LLSC TestNumber %ld\n", k_testnumber);
-
- for (i=0; i<k_linecount; i++) {
- printk(" %lx", blocks[i]);
- if (i%4 == 3)
- printk("\n");
- }
- printk("\n");
-}
-
-
-static void
-set_thread_state(int cpuid, int state)
-{
- if (k_threadprivate[cpuid]->threadstate == TS_KILLED) {
- set_led_bits(LED_MASK_AUTOTEST, LED_MASK_AUTOTEST);
- while(1);
- }
- k_threadprivate[cpuid]->threadstate = state;
-}
-
-#define MINBLK (16*1024*1024)
-static int
-build_mem_map(unsigned long start, unsigned long end, void *arg)
-{
- long lstart, lend;
- long align = 8*MB;
-
- printk ("LLSC memmap: start 0x%lx, end 0x%lx, (0x%lx - 0x%lx)\n",
- start, end, (long) virt_to_page(start), (long) virt_to_page(end-PAGE_SIZE));
-
- if (memmapx >= MAPCHUNKS || (end-start) < MINBLK)
- return 0;
-
- /*
- * Start in the middle of the range & find the first non-free page in both directions
- * from the midpoint. This is likely to be the bigest free block.
- */
- lend = lstart = start + (end-start)/2;
- while (lend < end && !PageReserved(virt_to_page(lend)) && virt_to_page(lend)->count.counter == 0)
- lend += PAGE_SIZE;
- lend -= PAGE_SIZE;
-
- while (lstart >= start && !PageReserved(virt_to_page(lstart)) && virt_to_page(lstart)->count.counter == 0)
- lstart -= PAGE_SIZE;
- lstart += PAGE_SIZE;
-
- lstart = (lstart + align -1) /align * align;
- end = end / align * align;
- if (lstart >= end)
- return 0;
- printk (" memmap: start 0x%lx, end 0x%lx\n", lstart, end);
-
- memmap[memmapx].vstart = lstart;
- memmap[memmapx].vend = end;
- memmapx++;
- return 0;
-}
-
-void int_test(void);
-
-int
-llsc_main (int cpuid)
-{
- int i, cpu, is_master, repeatcnt=0;
- unsigned int preverr=0, errs=0, pass=0;
- int automode=0;
-
-#ifdef INTTEST
- if (inttest)
- int_test();
-#endif
-
- if (!autotest_enabled)
- return 0;
-
-#ifdef CONFIG_SMP
- is_master = !smp_processor_id();
-#else
- is_master = 1;
-#endif
-
-
- if (is_master) {
- mbase = (control_t*) __get_free_pages(GFP_KERNEL, get_order(4096+THREADPRIVATESZ()*LLSC_MAXCPUS));
- printk("LLSC: mbase 0x%lx\n", (long)mbase);
- print_params();
- if(!IS_RUNNING_ON_SIMULATOR())
- spin(10);
- k_currentpass = 0;
- k_go = ST_IDLE;
- k_passes = DEF_PASSES;
- k_napticks = DEF_NAPTICKS;
- k_stop_on_error = DEF_STOP_ON_ERROR;
- k_verbose = DEF_VERBOSE;
- k_linecount = DEF_LINECOUNT;
- k_iter_msg = DEF_ITER_MSG;
- k_vv = DEF_VV;
- k_linepad = DEF_LINEPAD;
- k_blocks = (void*)blocks;
- efi_memmap_walk(build_mem_map, 0);
-
-#ifdef CONFIG_IA64_SGI_AUTOTEST
- automode = 1;
-#endif
-
- for (i=0; i<LLSC_MAXCPUS; i++) {
- k_threadprivate[i] = THREADPRIVATE(i);
- memset(k_threadprivate[i], 0, sizeof(*k_threadprivate[i]));
- init_private[i] = i;
- }
- mb();
- initialized = 1;
- } else {
- while (initialized == 0)
- udelay(100);
- }
-
-loop:
- if (is_master) {
- if (automode) {
- if (!preverr || repeatcnt++ > 5) {
- set_autotest_params();
- repeatcnt = 0;
- }
- } else {
- while (k_go == ST_IDLE);
- }
-
- k_go = ST_INIT;
- if (k_linecount > MAX_LINECOUNT) k_linecount = MAX_LINECOUNT;
- k_linecount = k_linecount & ~1;
- setup_block_addresses();
- if (!preverr && dump_block_addrs_opt)
- dump_block_addrs();
-
- k_currentpass = pass++;
- k_go = ST_RUN;
- if (fail_enabled)
- fail_enabled--;
-
- } else {
- while (k_go != ST_RUN || k_currentpass != pass);
- pass++;
- }
-
-
- set_leds(errs);
- set_thread_state(cpuid, TS_RUNNING);
-
- errs += ran_conf_llsc(cpuid);
- preverr = (k_go == ST_ERRSTOP);
-
- set_leds(errs);
- set_thread_state(cpuid, TS_STOPPED);
-
- if (is_master) {
- Speedo();
- for (i=0, cpu=0; cpu<LLSC_MAXCPUS; cpu++) {
- while (k_threadprivate[cpu]->threadstate == TS_RUNNING) {
- i++;
- if (i == 10000) {
- k_go = ST_STOP;
- printk (" llsc master stopping test number %ld\n", k_testnumber);
- }
- if (i > 100000) {
- k_threadprivate[cpu]->threadstate = TS_KILLED;
- printk (" llsc: master killing cpuid %d, running test number %ld\n",
- cpu, k_testnumber);
- }
- udelay(1000);
- }
- }
- }
-
- goto loop;
-}
-
-
-static void
-Speedo(void)
-{
- static int i = 0;
-
- switch (++i%4) {
- case 0:
- printk("|\b");
- break;
- case 1:
- printk("\\\b");
- break;
- case 2:
- printk("-\b");
- break;
- case 3:
- printk("/\b");
- break;
- }
-}
-
-#ifdef INTTEST
-
-/* ========================================================================================================
- *
- * Some test code to verify that interrupts work
- *
- * Add the following to the arch/ia64/kernel/smp.c after the comment "Reschedule callback"
- * if (zzzprint_resched) printk(" cpu %d got interrupt\n", smp_processor_id());
- *
- * Enable the code in arch/ia64/sn/sn1/smp.c to print sending IPIs.
- *
- */
-
-static int __init set_inttest(char *str)
-{
- inttest = 1;
- autotest_enabled = 1;
-
- return 1;
-}
-
-__setup("inttest=", set_inttest);
-
-int zzzprint_resched=0;
-
-void
-int_test() {
- int mycpu, cpu;
- static volatile int control_cpu=0;
-
- mycpu = smp_processor_id();
- zzzprint_resched = 2;
-
- printk("Testing cross interrupts\n");
-
- while (control_cpu != smp_num_cpus) {
- if (mycpu == cpu_logical_map(control_cpu)) {
- for (cpu=0; cpu<smp_num_cpus; cpu++) {
- printk("Sending interrupt from %d to %d\n", mycpu, cpu_logical_map(cpu));
- udelay(IS_RUNNING_ON_SIMULATOR ? 10000 : 400000);
- smp_send_reschedule(cpu_logical_map(cpu));
- udelay(IS_RUNNING_ON_SIMULATOR ? 10000 : 400000);
- smp_send_reschedule(cpu_logical_map(cpu));
- udelay(IS_RUNNING_ON_SIMULATOR ? 10000 : 400000);
- }
- control_cpu++;
- }
- }
-
- zzzprint_resched = 1;
-
- if (mycpu == cpu_logical_map(smp_num_cpus-1)) {
- printk("\nTight loop of cpu %d sending ints to cpu 0 (every 100 us)\n", mycpu);
- udelay(IS_RUNNING_ON_SIMULATOR ? 1000 : 1000000);
- __cli();
- while (1) {
- smp_send_reschedule(0);
- udelay(100);
- }
-
- }
-
- while(1);
-}
-#endif
diff --git a/arch/ia64/sn/kernel/llsc4.h b/arch/ia64/sn/kernel/llsc4.h
deleted file mode 100644
index 854fa14267a1b..0000000000000
--- a/arch/ia64/sn/kernel/llsc4.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifdef STANDALONE
-#include "lock.h"
-#endif
-
-
-#define DEF_NAPTICKS 0
-#define DEF_PASSES 0
-#define DEF_AUTO_PASSES 1000000
-#define DEF_STOP_ON_ERROR 1
-#define DEF_VERBOSE 0
-#define DEF_LINECOUNT 2
-#define DEF_ITER_MSG 0
-#define DEF_VV 0xffffffff
-#define DEF_LINEPAD 0x234
-
-
-
-#define LLSC_MAXCPUS 64
-#define CACHELINE 64
-#define MAX_LINECOUNT 1024
-#define K 1024
-#define MB (K*K)
-
-
-#define uint unsigned int
-#define ushort unsigned short
-#define uchar unsigned char
-#define vint volatile int
-#define vlong volatile long
-
-#define LOCKADDR(i) &linep->lock[(i)]
-#define LOCK(i) set_lock(LOCKADDR(i), lockpat)
-#define UNLOCK(i) clr_lock(LOCKADDR(i), lockpat)
-#define GETLOCK(i) *LOCKADDR(i)
-#define ZEROLOCK(i) init_lock(LOCKADDR(i))
-
-#define CACHEALIGN(a) ((char*)((long)(a) & ~127L))
-
-typedef uint guard_t;
-typedef uint lock_t;
-typedef uint share_t;
-typedef uchar private_t;
-
-typedef struct {
- guard_t guard1;
- lock_t lock[2];
- share_t share[2];
- private_t private[LLSC_MAXCPUS];
- share_t share0;
- share_t share1;
- guard_t guard2;
-} dataline_t ;
-
-
-#define LINEPAD k_linepad
-#define LINESTRIDE (((sizeof(dataline_t)+CACHELINE-1)/CACHELINE)*CACHELINE + LINEPAD)
-
-
-typedef struct {
- vint threadstate;
- uint threadpasses;
- private_t private[MAX_LINECOUNT];
-} threadprivate_t;
-
-typedef struct {
- vlong sk_go; /* 0=idle, 1=init, 2=run */
- long sk_linecount;
- long sk_passes;
- long sk_napticks;
- long sk_stop_on_error;
- long sk_verbose;
- long sk_iter_msg;
- long sk_vv;
- long sk_linepad;
- long sk_options;
- long sk_testnumber;
- vlong sk_currentpass;
- void *sk_blocks;
- threadprivate_t *sk_threadprivate[LLSC_MAXCPUS];
-} control_t;
-
-/* Run state (k_go) constants */
-#define ST_IDLE 0
-#define ST_INIT 1
-#define ST_RUN 2
-#define ST_STOP 3
-#define ST_ERRSTOP 4
-
-
-/* Threadstate constants */
-#define TS_STOPPED 0
-#define TS_RUNNING 1
-#define TS_KILLED 2
-
-
-
-int llsc_main (int cpuid);
-
diff --git a/arch/ia64/sn/kernel/machvec.c b/arch/ia64/sn/kernel/machvec.c
index 72a81f6f21d3a..010b0623b1f9d 100644
--- a/arch/ia64/sn/kernel/machvec.c
+++ b/arch/ia64/sn/kernel/machvec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -30,32 +30,5 @@
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
-#include <linux/config.h>
-
-#ifdef CONFIG_IA64_SGI_SN1
-#define MACHVEC_PLATFORM_NAME sn1
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_sn1.h>
-#else CONFIG_IA64_SGI_SN1
-#define MACHVEC_PLATFORM_NAME sn2
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_sn2.h>
-#else
-#error "unknown platform"
-#endif
-
+#define MACHVEC_PLATFORM_NAME sn2
#include <asm/machvec_init.h>
-#include <asm/io.h>
-#include <linux/pci.h>
-void*
-sn_mk_io_addr_MACRO
-
-dma_addr_t
-sn_pci_map_single_MACRO
-
-int
-sn_pci_map_sg_MACRO
-
-unsigned long
-sn_virt_to_phys_MACRO
-
-void *
-sn_phys_to_virt_MACRO
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
index cfbfa1c24aaa5..02a25836ebbb2 100644
--- a/arch/ia64/sn/kernel/mca.c
+++ b/arch/ia64/sn/kernel/mca.c
@@ -2,7 +2,7 @@
* File: mca.c
* Purpose: SN specific MCA code.
*
- * Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -34,247 +34,101 @@
*/
#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/smp_lock.h>
-#include <linux/acpi.h>
-#ifdef CONFIG_KDB
-#include <linux/kdb.h>
-#endif
-
-#include <asm/machvec.h>
-#include <asm/page.h>
-#include <asm/ptrace.h>
-#include <asm/system.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <asm/mca.h>
#include <asm/sal.h>
#include <asm/sn/sn_sal.h>
-#include <asm/mca.h>
-#include <asm/sn/mca.h>
-
-#include <asm/irq.h>
-#include <asm/hw_irq.h>
-#include <asm/smp.h>
-#include <asm/sn/sn_cpuid.h>
-
-static char *shub_mmr_names[] = {
- "sh_event_occurred",
- "sh_first_error",
- "sh_event_overflow",
-
-/* PI */
- "sh_pi_first_error",
- "sh_pi_error_summary",
- "sh_pi_error_overflow",
-
-/* PI HW */
- "sh_pi_error_detail_1",
- "sh_pi_error_detail_2",
- "sh_pi_hw_time_stamp",
-
-/* PI UCE */
- "sh_pi_uncorrected_detail_1",
- "sh_pi_uncorrected_detail_2",
- "sh_pi_uncorrected_detail_3",
- "sh_pi_uncorrected_detail_4",
- "sh_pi_uncor_time_stamp",
-
-/* PI CE */
- "sh_pi_corrected_detail_1",
- "sh_pi_corrected_detail_2",
- "sh_pi_corrected_detail_3",
- "sh_pi_corrected_detail_4",
- "sh_pi_cor_time_stamp",
-
-/* MD */
- "sh_mem_error_summary",
- "sh_mem_error_overflow",
-/* MD HW */
- "sh_misc_err_hdr_upper",
- "sh_misc_err_hdr_lower",
- "sh_md_dqlp_mmr_xperr_val",
- "sh_md_dqlp_mmr_yperr_val",
- "sh_md_dqrp_mmr_xperr_val",
- "sh_md_dqrp_mmr_yperr_val",
- "sh_md_hw_time_stamp",
-
-/* MD UCE */
- "sh_dir_uc_err_hdr_lower",
- "sh_dir_uc_err_hdr_upper",
- "sh_md_dqlp_mmr_xuerr1",
- "sh_md_dqlp_mmr_xuerr2",
- "sh_md_dqlp_mmr_yuerr1",
- "sh_md_dqlp_mmr_yuerr2",
- "sh_md_dqrp_mmr_xuerr1",
- "sh_md_dqrp_mmr_xuerr2",
- "sh_md_dqrp_mmr_yuerr1",
- "sh_md_dqrp_mmr_yuerr2",
- "sh_md_uncor_time_stamp",
-/* MD CE */
- "sh_dir_cor_err_hdr_lower",
- "sh_dir_cor_err_hdr_upper",
- "sh_md_dqlp_mmr_xcerr1",
- "sh_md_dqlp_mmr_xcerr2",
- "sh_md_dqlp_mmr_ycerr1",
- "sh_md_dqlp_mmr_ycerr2",
- "sh_md_dqrp_mmr_xcerr1",
- "sh_md_dqrp_mmr_xcerr2",
- "sh_md_dqrp_mmr_ycerr1",
- "sh_md_dqrp_mmr_ycerr2",
- "sh_md_cor_time_stamp",
-/* MD CE, UCE */
- "sh_md_dqls_mmr_xamopw_err",
- "sh_md_dqrs_mmr_yamopw_err",
-/* XN */
- "sh_xn_error_summary",
- "sh_xn_first_error",
- "sh_xn_error_overflow",
-
-/* XN HW */
- "sh_xniilb_error_summary",
- "sh_xniilb_first_error",
- "sh_xniilb_error_overflow",
- "sh_xniilb_error_detail_1",
- "sh_xniilb_error_detail_2",
- "sh_xniilb_error_detail_3",
-
- "sh_ni0_error_summary_1",
- "sh_ni0_first_error_1",
- "sh_ni0_error_overflow_1",
-
- "sh_ni0_error_summary_2",
- "sh_ni0_first_error_2",
- "sh_ni0_error_overflow_2",
- "sh_ni0_error_detail_1",
- "sh_ni0_error_detail_2",
- "sh_ni0_error_detail_3",
+/*
+ * Interval for calling SAL to poll for errors that do NOT cause error
+ * interrupts. SAL will raise a CPEI if any errors are present that
+ * need to be logged.
+ */
+#define CPEI_INTERVAL (5*HZ)
- "sh_ni1_error_summary_1",
- "sh_ni1_first_error_1",
- "sh_ni1_error_overflow_1",
- "sh_ni1_error_summary_2",
- "sh_ni1_first_error_2",
- "sh_ni1_error_overflow_2",
+struct timer_list sn_cpei_timer;
+void sn_init_cpei_timer(void);
- "sh_ni1_error_detail_1",
- "sh_ni1_error_detail_2",
- "sh_ni1_error_detail_3",
- "sh_xn_hw_time_stamp",
+/*
+ * print_hook
+ *
+ * This function is the callback routine that SAL calls to log error
+ * info for platform errors.
+ */
+static int
+print_hook(const char *fmt, ...)
+{
+ static int newline=1;
+ char buf[400], *p;
+ va_list args;
+ int len=0;
-/* XN HW & UCE & SBE */
- "sh_xnpi_error_summary",
- "sh_xnpi_first_error",
- "sh_xnpi_error_overflow",
- "sh_xnpi_error_detail_1",
- "sh_xnmd_error_summary",
- "sh_xnmd_first_error",
- "sh_xnmd_error_overflow",
- "sh_xnmd_ecc_err_report",
- "sh_xnmd_error_detail_1",
+ va_start(args, fmt);
+ if (newline) {
+ strcpy(buf, "+ ");
+ len += 2;
+ }
+ len += vsnprintf(buf+len, sizeof(buf)-len, fmt, args);
+
+ /* Prefix each line with "+ " to be consistent with mca.c. */
+ p = buf;
+ while ((p=strchr(p, '\n')) && *++p != '\0') {
+ memmove(p+2, p, 1+strlen(p));
+ strncpy(p, "+ ", 2);
+ len += 2;
+ }
+ newline = (p != 0);
-/* XN UCE */
- "sh_xn_uncorrected_detail_1",
- "sh_xn_uncorrected_detail_2",
- "sh_xn_uncorrected_detail_3",
- "sh_xn_uncorrected_detail_4",
- "sh_xn_uncor_time_stamp",
+ va_end(args);
+ printk("%s", buf);
+ return len;
+}
-/* XN CE */
- "sh_xn_corrected_detail_1",
- "sh_xn_corrected_detail_2",
- "sh_xn_corrected_detail_3",
- "sh_xn_corrected_detail_4",
- "sh_xn_cor_time_stamp",
-/* LB HW */
- "sh_lb_error_summary",
- "sh_lb_first_error",
- "sh_lb_error_overflow",
- "sh_lb_error_detail_1",
- "sh_lb_error_detail_2",
- "sh_lb_error_detail_3",
- "sh_lb_error_detail_4",
- "sh_lb_error_detail_5",
- "sh_junk_error_status",
-};
-void
-sal_log_plat_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
+/*
+ * ia64_sn2_platform_plat_specific_err_print
+ *
+ * Called by the MCA handler to log platform-specific errors.
+ */
+void
+ia64_sn2_platform_plat_specific_err_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
{
- sal_log_plat_info_t *sh_info = (sal_log_plat_info_t *) p_data;
- u64 *mmr_val = (u64 *)&(sh_info->shub_state);
- char **mmr_name = shub_mmr_names;
- int mmr_count = sizeof(sal_log_shub_state_t)>>3;
+ ia64_sn_plat_specific_err_print(print_hook, p_data - sect_len);
+}
- while(mmr_count) {
- if(*mmr_val) {
- prfunc("%-40s: %#016lx\n",*mmr_name, *mmr_val);
- }
- mmr_name++;
- mmr_val++;
- mmr_count--;
- }
-}
-void
-sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) {
+static void
+sn_cpei_handler(int irq, void *devid, struct pt_regs *regs)
+{
+ /*
+ * this function's sole purpose is to call SAL when we receive
+ * a CE interrupt from SHUB or when the timer routine decides
+ * we need to call SAL to check for CEs.
+ */
- struct ia64_sal_retval isrv;
-// this function's sole purpose is to call SAL when we receive
-// a CE interrupt from SHUB or when the timer routine decides
-// we need to call SAL to check for CEs.
+ /* CALL SAL_LOG_CE */
- // CALL SAL_LOG_CE
- SAL_CALL(isrv, SN_SAL_LOG_CE, irq, 0, 0, 0, 0, 0, 0);
+ ia64_sn_plat_cpei_handler();
}
-#include <linux/timer.h>
-#define CPEI_INTERVAL (HZ/100)
-struct timer_list sn_cpei_timer = TIMER_INITIALIZER(NULL, 0, 0);
-void sn_init_cpei_timer(void);
-
-void
+static void
sn_cpei_timer_handler(unsigned long dummy) {
- sn_cpei_handler(-1, NULL, NULL);
- del_timer(&sn_cpei_timer);
- sn_cpei_timer.expires = jiffies + CPEI_INTERVAL;
- add_timer(&sn_cpei_timer);
+ sn_cpei_handler(-1, NULL, NULL);
+ mod_timer(&sn_cpei_timer, jiffies + CPEI_INTERVAL);
}
void
sn_init_cpei_timer() {
- sn_cpei_timer.expires = jiffies + CPEI_INTERVAL;
+ sn_cpei_timer.expires = jiffies + CPEI_INTERVAL;
sn_cpei_timer.function = sn_cpei_timer_handler;
add_timer(&sn_cpei_timer);
}
-
-#ifdef ajmtestceintr
-
-struct timer_list sn_ce_timer;
-
-void
-sn_ce_timer_handler(long dummy) {
- unsigned long *pi_ce_error_inject_reg = 0xc00000092fffff00;
-
- *pi_ce_error_inject_reg = 0x0000000000000100;
- del_timer(&sn_ce_timer);
- sn_ce_timer.expires = jiffies + CPEI_INTERVAL;
- add_timer(&sn_ce_timer);
-}
-
-sn_init_ce_timer() {
- sn_ce_timer.expires = jiffies + CPEI_INTERVAL;
- sn_ce_timer.function = sn_ce_timer_handler;
- add_timer(&sn_ce_timer);
-}
-#endif /* ajmtestceintr */
diff --git a/arch/ia64/sn/kernel/misctest.c b/arch/ia64/sn/kernel/misctest.c
deleted file mode 100644
index 974c95e6be175..0000000000000
--- a/arch/ia64/sn/kernel/misctest.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/processor.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/timex.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/sn/intr.h>
-#include <asm/hw_irq.h>
-#include <asm/sn/leds.h>
-
-extern int autotest_enabled;
-long mcatest=0, debug0, debug1, debug2, debug3;
-
-#define HDELAY(t) (IS_RUNNING_ON_SIMULATOR() ? udelay(1) : udelay(t))
-
-/*
- * mcatest
- * mactest contains a decimal number (RPTT) where
- * R - flag, if non zero, run forever
- *
- * P - identifies when to run the test
- * 0 execute test at cpu 0 early init
- * 1 execute test at cpu 0 idle
- * 2 execute test at last (highest numbered) cpu idle
- * 3 execute test on all cpus at idle
- *
- * TT- identifies test to run
- * 01 = MCA via dup TLB dropin
- * 02 = MCA via garbage address
- * 03 = lfetch via garbage address
- * 05 = INIT self
- * 06 = INIT other cpu
- * 07 = INIT non-existent cpu
- * 10 = IPI stress test. Target cpu 0
- * 11 = IPI stress test. Target all cpus
- * 12 = TLB stress test
- * 13 = Park cpu (spinloop)
- * 14 = One shot TLB test with tlb spinlock
- * 15 = One shot TLB test
- * 16 = One shot TLB test sync'ed with RTC
- * 20 = set led to the cpuid & spin.
- * 21 = Try mixed cache/uncached refs & see what happens
- * 22 = Call SAL reboot
- * 23 = Call PAL halt
- */
-static int __init set_mcatest(char *str)
-{
- int val;
- get_option(&str, &val);
- mcatest = val;
- return 1;
-}
-__setup("mcatest=", set_mcatest);
-
-static int __init set_debug0(char *str)
-{
- int val;
- get_option(&str, &val);
- debug0 = val;
- return 1;
-}
-__setup("debug0=", set_debug0);
-
-static int __init set_debug1(char *str)
-{
- int val;
- get_option(&str, &val);
- debug1 = val;
- return 1;
-}
-__setup("debug1=", set_debug1);
-
-static int __init set_debug2(char *str)
-{
- int val;
- get_option(&str, &val);
- debug2 = val;
- return 1;
-}
-__setup("debug2=", set_debug2);
-
-static int __init set_debug3(char *str)
-{
- int val;
- get_option(&str, &val);
- debug3 = val;
- return 1;
-}
-__setup("debug3=", set_debug3);
-
-static volatile int go;
-
-static void
-do_sync(int pos) {
- if (pos != 3)
- return;
- else if (smp_processor_id() == 0)
- go = 1;
- else
- while (!go);
-}
-
-static void
-sgi_mcatest_bkpt(void)
-{
-}
-
-
-/*
- * Optional test
- * pos - 0 called from early init
- * pos - called when cpu about to go idle (fully initialized
- */
-void
-sgi_mcatest(int pos)
-{
- long spos, test, repeat;
- int cpu, curcpu, i, n;
-
- //if (IS_RUNNING_ON_SIMULATOR()) mcatest=1323;
- repeat = mcatest/1000;
- spos = (mcatest/100)%10;
- test = mcatest % 100;
- curcpu = smp_processor_id();
-
- if ( mcatest == 0 || !((pos == 0 && spos == 0) ||
- (pos == 1 && spos == 3) ||
- (pos == 1 && spos == 1 && curcpu == 0) ||
- (pos == 1 && spos == 2 && curcpu == smp_num_cpus-1)))
- return;
-
-again:
- if (test == 1 || test == 2 || test == 3) {
- void zzzmca(int);
- printk("CPU %d: About to cause unexpected MCA\n", curcpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- zzzmca(test-1);
-
- HDELAY(100000);
- }
-
- if (test == 4) {
- long result, adrs[] = {0xe0021000009821e0UL, 0xc0003f3000000000UL, 0xc0000081101c0000UL, 0xc00000180e021004UL, 0xc00000180e022004UL, 0xc00000180e023004UL };
- long size[] = {1,2,4,8};
- int r, i, j, k;
-
- for (k=0; k<2; k++) {
- for (i=0; i<6; i++) {
- for (j=0; j<4; j++) {
- printk("Probing 0x%lx, size %ld\n", adrs[i], size[j]);
- result = -1;
- r = ia64_sn_probe_io_slot (adrs[i], size[j], &result);
- printk(" status %d, val 0x%lx\n", r, result);
- udelay(100000);
- }
- }
- }
-
- }
-
- if (test == 5) {
- cpu = curcpu;
- printk("CPU %d: About to send INIT to self (cpu %d)\n", curcpu, cpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
-
- HDELAY(100000);
- printk("CPU %d: Returned from INIT\n", curcpu);
- }
-
- if (test == 6) {
- cpu = curcpu ^ 1;
- printk("CPU %d: About to send INIT to other cpu (cpu %d)\n", curcpu, cpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
-
- HDELAY(100000);
- printk("CPU %d: Done\n", curcpu);
- }
-
- if (test == 7) {
- printk("CPU %d: About to send INIT to non-existent cpu\n", curcpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- sn_send_IPI_phys(0xffff, 0, IA64_IPI_DM_INIT);
-
- HDELAY(100000);
- printk("CPU %d: Done\n", curcpu);
- }
-
- if (test == 10) {
- n = IS_RUNNING_ON_SIMULATOR() ? 10 : 10000000;
- cpu = 0;
- printk("CPU %d: IPI stress test. Target cpu 0\n", curcpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- for (i=0; i<n; i++)
- platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
-
- HDELAY(100000);
- printk("CPU %d: Done\n", curcpu);
- }
-
- if (test == 11) {
- n = IS_RUNNING_ON_SIMULATOR() ? 100 : 10000000;
- printk("CPU %d: IPI stress test. Target all cpus\n", curcpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- for (i=0; i<n; i++)
- for (cpu=0; cpu<smp_num_cpus; cpu++)
- if (smp_num_cpus > 2 && cpu != curcpu)
- platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
-
- HDELAY(100000);
- printk("CPU %d: Done\n", curcpu);
- }
-
- if (test == 12) {
- long adr = 0xe002200000000000UL;
- n = IS_RUNNING_ON_SIMULATOR() ? 1000 : 100000;
- printk("CPU %d: TLB flush stress test\n", curcpu);
- HDELAY(100000);
- sgi_mcatest_bkpt();
- do_sync(spos);
-
- for (i=0; i<n; i++)
- platform_global_tlb_purge(adr, adr+25*PAGE_SIZE, 14);
-
- HDELAY(100000);
- printk("CPU %d: Done\n", curcpu);
- }
-
- if (test == 13) {
- printk("CPU %d: Park cpu in spinloop\n", curcpu);
- while(1);
- }
- if (test == 14 || test == 15 || test == 16 || test == 17) {
- long adr = 0xe002200000000000UL;
- static int inited=0;
- if (inited == 0) {
- if (debug0 == 0) debug0 = 1;
- repeat = 1;
- do_sync(spos);
- if (curcpu >= smp_num_cpus-2) {
- printk("Parking cpu %d\n", curcpu);
- local_irq_disable();
- while(1);
- } else {
- printk("Waiting cpu %d\n", curcpu);
- HDELAY(1000000);
- }
- HDELAY(1000000);
- inited = 1;
- }
- if (test == 16 || test == 17) {
- unsigned long t, shift, mask;
- mask = (smp_num_cpus > 16) ? 0x1f : 0xf;
- shift = 25-debug1;
- do {
- t = get_cycles();
- if (IS_RUNNING_ON_SIMULATOR())
- t = (t>>8);
- else
- t = (t>>shift);
- t = t & mask;
- } while (t == curcpu);
- do {
- t = get_cycles();
- if (IS_RUNNING_ON_SIMULATOR())
- t = (t>>8);
- else
- t = (t>>shift);
- t = t & mask;
- } while (t != curcpu);
- }
- if(debug3) printk("CPU %d: One TLB start\n", curcpu);
- if (test != 17) platform_global_tlb_purge(adr, adr+PAGE_SIZE*debug0, 14);
- if(debug3) printk("CPU %d: One TLB flush done\n", curcpu);
- }
- if (test == 20) {
- local_irq_disable();
- set_led_bits(smp_processor_id(), 0xff);
- while(1);
- }
- if (test == 21) {
- extern long ia64_mca_stack[];
- int i, n;
- volatile long *p, *up;
- p = (volatile long*)__imva(ia64_mca_stack);
- up = (volatile long*)(__pa(p) | __IA64_UNCACHED_OFFSET);
-
- if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ get data in cache\n");
- for (n=0, i=0; i<100; i++)
- n += *(p+i);
- if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Make uncached refs to same data\n");
- for (n=0, i=0; i<100; i++)
- n += *(up+i);
- if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ dirty the data via cached refs\n");
- for (n=0, i=0; i<100; i++)
- *(p+i) = i;
- if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Make uncached refs to same data\n");
- for (n=0, i=0; i<100; i++)
- n += *(up+i);
- if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Flushing cache\n");
- for (n=0, i=0; i<100; i++)
- ia64_fc((void*)(p+i));
- printk("ZZZ done\n");
- }
- if (test == 21) {
- int i;
- volatile long tb, t[10];
- for (i=0; i<10; i++) {
- tb = debug3+ia64_get_itc();
- sgi_mcatest_bkpt();
- t[i] = ia64_get_itc() - tb;
- }
- for (i=0; i<10; i++) {
- printk("ZZZ NULL 0x%lx\n", t[i]);
- }
- for (i=0; i<10; i++) {
- tb = debug3+ia64_get_itc();
- ia64_pal_call_static(PAL_MC_DRAIN, 0, 0, 0, 0);
- t[i] = ia64_get_itc() - tb;
- }
- for (i=0; i<10; i++) {
- printk("ZZZ DRAIN 0x%lx\n", t[i]);
- }
- }
- if (test == 22) {
- extern void machine_restart(char*);
- printk("ZZZ machine_restart\n");
- machine_restart(0);
- }
- if (test == 23) {
- printk("ZZZ ia64_pal_halt_light\n");
- ia64_pal_halt_light();
- }
- if (repeat)
- goto again;
-
-}
diff --git a/arch/ia64/sn/kernel/probe.c b/arch/ia64/sn/kernel/probe.c
index 4b2cf42c2841e..e00518746db47 100644
--- a/arch/ia64/sn/kernel/probe.c
+++ b/arch/ia64/sn/kernel/probe.c
@@ -1,7 +1,7 @@
/*
* Platform dependent support for IO probing.
*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 363a87497284e..8831bd886e36e 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -69,18 +69,17 @@
#include <asm/sn/bte.h>
#include <asm/sn/clksupport.h>
#include <asm/sn/sn_sal.h>
-
-#ifdef CONFIG_IA64_SGI_SN2
#include <asm/sn/sn2/shub.h>
-#endif
DEFINE_PER_CPU(struct pda_s, pda_percpu);
+#define pxm_to_nasid(pxm) ((pxm)<<1)
+
extern void bte_init_node (nodepda_t *, cnodeid_t);
extern void bte_init_cpu (void);
extern void sn_timer_init (void);
extern void (*ia64_mark_idle)(int);
-extern void snidle(int);
+void snidle(int);
unsigned long sn_rtc_cycles_per_second;
@@ -88,6 +87,8 @@ partid_t sn_partid = -1;
char sn_system_serial_number_string[128];
u64 sn_partition_serial_number;
+short physical_node_map[MAX_PHYSNODE_ID];
+
/*
* This is the address of the RRegs in the HSpace of the global
* master. It is used by a hack in serial.c (serial_[in|out],
@@ -96,21 +97,14 @@ u64 sn_partition_serial_number;
* early_printk won't try to access the UART before
* master_node_bedrock_address is properly calculated.
*/
-u64 master_node_bedrock_address = 0UL;
+u64 master_node_bedrock_address;
static void sn_init_pdas(char **);
-extern struct irq_desc *_sn_irq_desc[];
-
-#if defined(CONFIG_IA64_SGI_SN1)
-extern synergy_da_t *Synergy_da_indr[];
-#endif
static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
-#ifdef CONFIG_IA64_SGI_SN2
-irqpda_t *irqpdaindr[NR_CPUS];
-#endif /* CONFIG_IA64_SGI_SN2 */
+irqpda_t *irqpdaindr;
/*
@@ -137,29 +131,19 @@ struct screen_info sn_screen_info = {
* running in the simulator. Note that passing zeroes in DRIVE_INFO
* is sufficient (the IDE driver will autodetect the drive geometry).
*/
+#ifdef CONFIG_IA64_GENERIC
+extern char drive_info[4*16];
+#else
char drive_info[4*16];
-
-/**
- * sn_map_nr - return the mem_map entry for a given kernel address
- * @addr: kernel address to query
- *
- * Finds the mem_map entry for the kernel address given. Used by
- * virt_to_page() (asm-ia64/page.h), among other things.
- */
-unsigned long
-sn_map_nr (unsigned long addr)
-{
- return BANK_MAP_NR(addr);
-}
+#endif
/**
* early_sn_setup - early setup routine for SN platforms
*
* Sets up an initial console to aid debugging. Intended primarily
- * for bringup, it's only called if %BRINGUP and %CONFIG_IA64_EARLY_PRINTK
- * are turned on. See start_kernel() in init/main.c.
+ * for bringup. See start_kernel() in init/main.c.
*/
-#if defined(CONFIG_IA64_EARLY_PRINTK)
+#if defined(CONFIG_IA64_EARLY_PRINTK) || defined(CONFIG_IA64_SGI_SN_SIM)
void __init
early_sn_setup(void)
@@ -197,21 +181,48 @@ early_sn_setup(void)
}
if ( IS_RUNNING_ON_SIMULATOR() ) {
-#if defined(CONFIG_IA64_SGI_SN1)
- master_node_bedrock_address = (u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
-#else
master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
-#endif
printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address);
}
}
-#endif /* CONFIG_IA64_SGI_SN1 */
+#endif /* CONFIG_IA64_EARLY_PRINTK */
#ifdef CONFIG_IA64_MCA
extern int platform_intr_list[];
#endif
extern nasid_t master_nasid;
+static int shub_1_1_found __initdata;
+
+
+/*
+ * sn_check_for_wars
+ *
+ * Set flag for enabling shub specific wars
+ */
+
+static inline int __init
+is_shub_1_1(int nasid)
+{
+ unsigned long id;
+ int rev;
+
+ id = REMOTE_HUB_L(nasid, SH_SHUB_ID);
+ rev = (id & SH_SHUB_ID_REVISION_MASK) >> SH_SHUB_ID_REVISION_SHFT;
+ return rev <= 2;
+}
+
+static void __init
+sn_check_for_wars(void)
+{
+ int cnode;
+
+ for (cnode=0; cnode< numnodes; cnode++)
+ if (is_shub_1_1(cnodeid_to_nasid(cnode)))
+ shub_1_1_found = 1;
+}
+
+
/**
* sn_setup - SN platform setup routine
@@ -225,8 +236,18 @@ void __init
sn_setup(char **cmdline_p)
{
long status, ticks_per_sec, drift;
- int i;
+ int pxm;
int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
+ extern void io_sh_swapper(int, int);
+ extern nasid_t get_master_baseio_nasid(void);
+ extern void sn_cpu_init(void);
+
+ MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
+
+ memset(physical_node_map, -1, sizeof(physical_node_map));
+ for (pxm=0; pxm<MAX_PXM_DOMAINS; pxm++)
+ if (pxm_to_nid_map[pxm] != -1)
+ physical_node_map[pxm_to_nasid(pxm)] = pxm_to_nid_map[pxm];
printk("SGI SAL version %x.%02x\n", major, minor);
@@ -239,23 +260,13 @@ sn_setup(char **cmdline_p)
"%x.%02x\n", SN_SAL_MIN_MAJOR, SN_SAL_MIN_MINOR);
panic("PROM version too old\n");
}
-#ifdef CONFIG_PCI
-#ifdef CONFIG_IA64_SGI_SN2
- {
- extern void io_sh_swapper(int, int);
- io_sh_swapper(get_nasid(), 0);
- }
-#endif
+
+ io_sh_swapper(get_nasid(), 0);
master_nasid = get_nasid();
(void)get_console_nasid();
-#ifndef CONFIG_IA64_SGI_SN1
- {
- extern nasid_t get_master_baseio_nasid(void);
- (void)get_master_baseio_nasid();
- }
-#endif
-#endif /* CONFIG_PCI */
+ (void)get_master_baseio_nasid();
+
status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift);
if (status != 0 || ticks_per_sec < 100000) {
printk(KERN_WARNING "unable to determine platform RTC clock frequency, guessing.\n");
@@ -265,19 +276,12 @@ sn_setup(char **cmdline_p)
else
sn_rtc_cycles_per_second = ticks_per_sec;
- for (i=0;i<NR_CPUS;i++)
- _sn_irq_desc[i] = _irq_desc;
-
platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_PCE_VECTOR;
if ( IS_RUNNING_ON_SIMULATOR() )
{
-#ifdef CONFIG_IA64_SGI_SN2
master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
-#else
- master_node_bedrock_address = (u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
-#endif
printk(KERN_DEBUG "sn_setup: setting master_node_bedrock_address to 0x%lx\n",
master_node_bedrock_address);
}
@@ -287,6 +291,10 @@ sn_setup(char **cmdline_p)
*/
sn_init_pdas(cmdline_p);
+ /*
+ * Check for WARs.
+ */
+ sn_check_for_wars();
/*
* For the bootcpu, we do this here. All other cpus will make the
@@ -300,11 +308,6 @@ sn_setup(char **cmdline_p)
#endif
screen_info = sn_screen_info;
- /*
- * Turn off "floating-point assist fault" warnings by default.
- */
- current->thread.flags |= IA64_THREAD_FPEMU_NOPRINT;
-
sn_timer_init();
ia64_mark_idle = &snidle;
@@ -324,22 +327,19 @@ sn_init_pdas(char **cmdline_p)
* Make sure that the PDA fits entirely in the same page as the
* cpu_data area.
*/
- if ( (((unsigned long)pda & ~PAGE_MASK) + sizeof(pda_t)) > PAGE_SIZE)
+ if ((((unsigned long)pda & (~PAGE_MASK)) + sizeof(pda_t)) > PAGE_SIZE)
panic("overflow of cpu_data page");
+ memset(pda->cnodeid_to_nasid_table, -1, sizeof(pda->cnodeid_to_nasid_table));
+ for (cnode=0; cnode<numnodes; cnode++)
+ pda->cnodeid_to_nasid_table[cnode] = pxm_to_nasid(nid_to_pxm_map[cnode]);
+
/*
* Allocate & initalize the nodepda for each node.
*/
for (cnode=0; cnode < numnodes; cnode++) {
nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t));
memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
-
-#if defined(CONFIG_IA64_SGI_SN1)
- Synergy_da_indr[cnode * 2] = (synergy_da_t *) alloc_bootmem_node(NODE_DATA(cnode), sizeof(synergy_da_t));
- Synergy_da_indr[cnode * 2 + 1] = (synergy_da_t *) alloc_bootmem_node(NODE_DATA(cnode), sizeof(synergy_da_t));
- memset(Synergy_da_indr[cnode * 2], 0, sizeof(synergy_da_t));
- memset(Synergy_da_indr[cnode * 2 + 1], 0, sizeof(synergy_da_t));
-#endif
}
/*
@@ -348,7 +348,7 @@ sn_init_pdas(char **cmdline_p)
for (cnode=0; cnode < numnodes; cnode++)
memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr));
-#ifdef CONFIG_PCI
+
/*
* Set up IO related platform-dependent nodepda fields.
* The following routine actually sets up the hubinfo struct
@@ -358,7 +358,6 @@ sn_init_pdas(char **cmdline_p)
init_platform_nodepda(nodepdaindr[cnode], cnode);
bte_init_node (nodepdaindr[cnode], cnode);
}
-#endif
}
/**
@@ -373,7 +372,11 @@ sn_init_pdas(char **cmdline_p)
void __init
sn_cpu_init(void)
{
- int cpuid, cpuphyid, nasid, nodeid, slice;
+ int cpuid;
+ int cpuphyid;
+ int nasid;
+ int slice;
+ int cnode, i;
/*
* The boot cpu makes this call again after platform initialization is
@@ -385,14 +388,43 @@ sn_cpu_init(void)
cpuid = smp_processor_id();
cpuphyid = ((ia64_get_lid() >> 16) & 0xffff);
nasid = cpu_physical_id_to_nasid(cpuphyid);
- nodeid = cpu_to_node_map[cpuphyid];
+ cnode = nasid_to_cnodeid(nasid);
slice = cpu_physical_id_to_slice(cpuphyid);
- memset(pda, 0, sizeof(pda_t));
- pda->p_nodepda = nodepdaindr[nodeid];
+ printk("CPU %d: nasid %d, slice %d, cnode %d\n",
+ smp_processor_id(), nasid, slice, cnode);
+
+ memset(pda, 0, sizeof(pda));
+ pda->p_nodepda = nodepdaindr[cnode];
+ pda->led_address = (typeof(pda->led_address)) (LED0 + (slice<<LED_CPU_SHIFT));
+ pda->led_state = LED_ALWAYS_SET;
pda->hb_count = HZ/2;
pda->hb_state = 0;
pda->idle_flag = 0;
+ pda->shub_1_1_found = shub_1_1_found;
+
+ memset(pda->cnodeid_to_nasid_table, -1, sizeof(pda->cnodeid_to_nasid_table));
+ for (i=0; i<numnodes; i++)
+ pda->cnodeid_to_nasid_table[i] = pxm_to_nasid(nid_to_pxm_map[i]);
+
+ if (local_node_data->active_cpu_count == 1)
+ nodepda->node_first_cpu = cpuid;
+
+
+
+ /*
+ * We must use different memory allocators for first cpu (bootmem
+ * allocator) than for the other cpus (regular allocator).
+ */
+ if (cpuid == 0)
+ irqpdaindr = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t));
+
+ memset(irqpdaindr, 0, sizeof(irqpda_t));
+ irqpdaindr->irq_flags[SGI_PCIBR_ERROR] = SN2_IRQ_SHARED;
+ irqpdaindr->irq_flags[SGI_PCIBR_ERROR] |= SN2_IRQ_RESERVED;
+ irqpdaindr->irq_flags[SGI_II_ERROR] = SN2_IRQ_SHARED;
+ irqpdaindr->irq_flags[SGI_II_ERROR] |= SN2_IRQ_RESERVED;
+
pda->pio_write_status_addr = (volatile unsigned long *)
LOCAL_MMR_ADDR((slice < 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1 ) );
pda->mem_write_status_addr = (volatile u64 *)
@@ -400,89 +432,25 @@ sn_cpu_init(void)
if (nodepda->node_first_cpu == cpuid) {
int buddy_nasid;
- buddy_nasid = cnodeid_to_nasid(local_nodeid == numnodes - 1 ? 0 : local_nodeid + 1);
+ buddy_nasid = cnodeid_to_nasid(numa_node_id() == numnodes-1 ? 0 : numa_node_id()+ 1);
pda->pio_shub_war_cam_addr = (volatile unsigned long*)GLOBAL_MMR_ADDR(nasid, SH_PI_CAM_CONTROL);
}
bte_init_cpu();
}
-#ifdef II_PRTE_TLB_WAR
-long iiprt_lock[16*64] __cacheline_aligned; /* allow for NASIDs up to 64 */
-#endif
-
-#ifdef BUS_INT_WAR
-
-#include <asm/hw_irq.h>
-#include <asm/sn/pda.h>
-
-void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs);
-
-static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;
-
-#define IRQCPU(irq) ((irq)>>8)
-
-void
-sn_add_polled_interrupt(int irq, int interval)
-{
- unsigned long flags, irq_cnt;
- sn_poll_entry_t *irq_list;
-
- irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries;;
-
- spin_lock_irqsave(&irq_lock, flags);
- irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count;
- irq_list[irq_cnt].irq = irq;
- irq_list[irq_cnt].interval = interval;
- irq_list[irq_cnt].tick = interval;
- pdacpu(IRQCPU(irq)).pda_poll_entry_count++;
- spin_unlock_irqrestore(&irq_lock, flags);
-
-
-}
-
-void
-sn_delete_polled_interrupt(int irq)
+void snidle(int idleness)
{
- unsigned long flags, i, irq_cnt;
- sn_poll_entry_t *irq_list;
-
- irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries;
-
- spin_lock_irqsave(&irq_lock, flags);
- irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count;
- for (i=0; i<irq_cnt; i++) {
- if (irq_list[i].irq == irq) {
- irq_list[i] = irq_list[irq_cnt-1];
- pdacpu(IRQCPU(irq)).pda_poll_entry_count--;
- break;
+ if (!idleness) {
+ if (pda->idle_flag == 0) {
+ set_led_bits(0, LED_CPU_ACTIVITY);
}
- }
- spin_unlock_irqrestore(&irq_lock, flags);
-}
-void
-sn_irq_poll(int cpu, int reason)
-{
- unsigned long flags, i;
- sn_poll_entry_t *irq_list;
-
-
- ia64_handle_irq(IA64_IPI_VECTOR, 0);
-
- if (reason == 0)
- return;
-
- irq_list = pda->pda_poll_entries;
-
- for (i=0; i<pda->pda_poll_entry_count; i++, irq_list++) {
- if (--irq_list->tick <= 0) {
- irq_list->tick = irq_list->interval;
- local_irq_save(flags);
- ia64_handle_irq(irq_to_vector(irq_list->irq), 0);
- local_irq_restore(flags);
- }
+ pda->idle_flag = 1;
}
-}
+ else {
+ set_led_bits(LED_CPU_ACTIVITY, LED_CPU_ACTIVITY);
-#endif
+ pda->idle_flag = 0;
+ }
+}
diff --git a/arch/ia64/sn/kernel/sn1/Makefile b/arch/ia64/sn/kernel/sn1/Makefile
deleted file mode 100644
index 65261dc37f5d2..0000000000000
--- a/arch/ia64/sn/kernel/sn1/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# arch/ia64/sn/kernel/sn1/Makefile
-#
-# Copyright (C) 1999,2001-2002 Silicon Graphics, Inc. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of version 2 of the GNU General Public License
-# as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like. Any license provided herein, whether implied or
-# otherwise, applies only to this software file. Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public
-# License along with this program; if not, write the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
-# Mountain View, CA 94043, or:
-#
-# http://www.sgi.com
-#
-# For further information regarding this notice, see:
-#
-# http://oss.sgi.com/projects/GenInfo/NoticeExplan
-#
-
-
-EXTRA_CFLAGS := -DLITTLE_ENDIAN
-
-.S.s:
- $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -o $*.s $<
-.S.o:
- $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $<
-
-O_TARGET = sn1.o
-
-obj-y = cache.o error.o iomv.o synergy.o sn1_smp.o
diff --git a/arch/ia64/sn/kernel/sn1/cache.c b/arch/ia64/sn/kernel/sn1/cache.c
deleted file mode 100644
index c0894b03fca09..0000000000000
--- a/arch/ia64/sn/kernel/sn1/cache.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved.
- *
- */
-
-#include <linux/kernel.h>
-#include <asm/pgalloc.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/sn1/synergy.h>
-#include <asm/delay.h>
-
-#ifndef MB
-#define MB (1024*1024)
-#endif
-
-/*
- * Lock for protecting SYN_TAG_DISABLE_WAY.
- * Consider making this a per-FSB lock.
- */
-static spinlock_t flush_lock = SPIN_LOCK_UNLOCKED;
-
-/**
- * sn_flush_all_caches - flush a range of addresses from all caches (incl. L4)
- * @flush_addr: identity mapped region 7 address to start flushing
- * @bytes: number of bytes to flush
- *
- * Flush a range of addresses from all caches including L4. All addresses
- * fully or partially contained within @flush_addr to @flush_addr + @bytes
- * are flushed from the all caches.
- */
-void
-sn_flush_all_caches(long flush_addr, long bytes)
-{
- ulong addr, baddr, eaddr, bitbucket;
- int way, alias;
-
- /*
- * Because of the way synergy implements "fc", this flushes the
- * data from all caches on all cpus & L4's on OTHER FSBs. It also
- * flushes both cpus on the local FSB. It does NOT flush it from
- * the local FSB.
- */
- flush_icache_range(flush_addr, flush_addr+bytes);
-
- /*
- * Memory DIMMs are a minimum of 256MB and start on 256MB
- * boundaries. Convert the start address to an address
- * that is between +0MB & +128 of the same DIMM.
- * Then add 8MB to skip the uncached MinState areas if the address
- * is on the master node.
- */
- if (bytes > SYNERGY_L4_BYTES_PER_WAY)
- bytes = SYNERGY_L4_BYTES_PER_WAY;
- baddr = TO_NODE(smp_physical_node_id(), PAGE_OFFSET + (flush_addr & (128*MB-1)) + 8*MB);
- eaddr = (baddr+bytes+SYNERGY_BLOCK_SIZE-1) & ~(SYNERGY_BLOCK_SIZE-1);
- baddr = baddr & ~(SYNERGY_BLOCK_SIZE-1);
-
- /*
- * Now flush the local synergy.
- */
- spin_lock(&flush_lock);
- for(way=0; way<SYNERGY_L4_WAYS; way++) {
- WRITE_LOCAL_SYNERGY_REG(SYN_TAG_DISABLE_WAY, 0xffL ^ (1L<<way));
- mb();
- for(alias=0; alias < 9; alias++)
- for(addr=baddr; addr<eaddr; addr+=SYNERGY_BLOCK_SIZE)
- bitbucket = *(volatile ulong *)(addr+alias*8*MB);
- mb();
- }
- WRITE_LOCAL_SYNERGY_REG(SYN_TAG_DISABLE_WAY, 0);
- spin_unlock(&flush_lock);
-
-}
-
-
diff --git a/arch/ia64/sn/kernel/sn1/error.c b/arch/ia64/sn/kernel/sn1/error.c
deleted file mode 100644
index 16b68ae0012b4..0000000000000
--- a/arch/ia64/sn/kernel/sn1/error.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * SN1 Platform specific error Support
- *
- * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/ptrace.h>
-#include <linux/devfs_fs_kernel.h>
-#include <asm/smp.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/sn1/bedrock.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/addrs.h>
-
-/**
- * snia_error_intr_handler - handle SN specific error interrupts
- * @irq: error interrupt received
- * @devid: device causing the interrupt
- * @pt_regs: saved register state
- *
- * This routine is called when certain interrupts occur on SN systems.
- * It will either recover from the situations that caused the interrupt
- * or panic.
- */
-void
-snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs)
-{
- unsigned long long intpend_val;
- unsigned long long bit;
-
- switch (irq) {
- case SGI_UART_IRQ:
- /*
- * This isn't really an error interrupt. We're just
- * here because we have to do something with them.
- * This is probably wrong, and this code will be
- * removed.
- */
- intpend_val = LOCAL_HUB_L(PI_INT_PEND0);
- if ( (bit = ~(1L<<GFX_INTR_A)) ==
- (intpend_val & ~(1L<<GFX_INTR_A)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- if ( (bit = ~(1L<<GFX_INTR_B)) ==
- (intpend_val & ~(1L<<GFX_INTR_B)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- if ( (bit = ~(1L<<PG_MIG_INTR)) ==
- (intpend_val & ~(1L<<PG_MIG_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- if ( (bit = ~(1L<<UART_INTR)) ==
- (intpend_val & ~(1L<<UART_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- if ( (bit = ~(1L<<CC_PEND_A)) ==
- (intpend_val & ~(1L<<CC_PEND_A)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- if ( (bit = ~(1L<<CC_PEND_B)) ==
- (intpend_val & ~(1L<<CC_PEND_B)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- return;
- }
- printk("Received SGI_UART_IRQ (65), but no intpend0 bits were set???\n");
- return;
- case SGI_HUB_ERROR_IRQ:
- /*
- * These are mostly error interrupts of various
- * sorts. We need to do more than panic here, but
- * what the heck, this is bring up.
- */
- intpend_val = LOCAL_HUB_L(PI_INT_PEND1);
-
- if ( (bit = ~(1L<<XB_ERROR)) ==
- (intpend_val & ~(1L<<XB_ERROR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED XB_ERROR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<LB_ERROR)) ==
- (intpend_val & ~(1L<<LB_ERROR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED LB_ERROR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<NACK_INT_A)) ==
- (intpend_val & ~(1L<<NACK_INT_A)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED NACK_INT_A on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<NACK_INT_B)) ==
- (intpend_val & ~(1L<<NACK_INT_B)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED NACK_INT_B on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<CLK_ERR_INTR)) ==
- (intpend_val & ~(1L<<CLK_ERR_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED CLK_ERR_INTR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<COR_ERR_INTR_A)) ==
- (intpend_val & ~(1L<<COR_ERR_INTR_A)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED COR_ERR_INTR_A on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<COR_ERR_INTR_B)) ==
- (intpend_val & ~(1L<<COR_ERR_INTR_B)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED COR_ERR_INTR_B on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<MD_COR_ERR_INTR)) ==
- (intpend_val & ~(1L<<MD_COR_ERR_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED MD_COR_ERR_INTR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<NI_ERROR_INTR)) ==
- (intpend_val & ~(1L<<NI_ERROR_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED NI_ERROR_INTR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- if ( (bit = ~(1L<<MSC_PANIC_INTR)) ==
- (intpend_val & ~(1L<<MSC_PANIC_INTR)) ) {
- LOCAL_HUB_CLR_INTR(bit);
- panic("RECEIVED MSC_PANIC_INTR on cpu %d, cnode %d\n",
- smp_processor_id(),
- cpuid_to_cnodeid(smp_processor_id()));
- }
- printk("Received SGI_XB_ERROR_IRQ (182) but no intpend1 bits are set???\n");
- return;
- default:
- printk("Received invalid irq in snia_error_intr_handler()\n");
- }
-}
diff --git a/arch/ia64/sn/kernel/sn1/iomv.c b/arch/ia64/sn/kernel/sn1/iomv.c
deleted file mode 100644
index 04bd87614c90c..0000000000000
--- a/arch/ia64/sn/kernel/sn1/iomv.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/sn/simulator.h>
-#include <asm/delay.h>
-#include <asm/sn/pda.h>
-
-/**
- * sn_io_addr - convert an in/out port to an i/o address
- * @port: port to convert
- *
- * Legacy in/out instructions are converted to ld/st instructions
- * on IA64. This routine will convert a port number into a valid
- * SN i/o address. Used by sn_in*() and sn_out*().
- */
-void *
-sn_io_addr(unsigned long port)
-{
- if (!IS_RUNNING_ON_SIMULATOR()) {
- return( (void *) (port | __IA64_UNCACHED_OFFSET));
- } else {
- unsigned long io_base;
- unsigned long addr;
-
- /*
- * word align port, but need more than 10 bits
- * for accessing registers in bedrock local block
- * (so we don't do port&0xfff)
- */
- if ((port >= 0x1f0 && port <= 0x1f7) ||
- port == 0x3f6 || port == 0x3f7) {
- io_base = __IA64_UNCACHED_OFFSET | 0x00000FFFFC000000;
- addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
- } else {
- addr = __ia64_get_io_port_base() | ((port >> 2) << 2);
- }
- return(void *) addr;
- }
-}
-
-/**
- * sn1_mmiob - I/O space memory barrier
- *
- * Acts as a memory mapped I/O barrier for platforms that queue writes to
- * I/O space. This ensures that subsequent writes to I/O space arrive after
- * all previous writes. For most ia64 platforms, this is a simple
- * 'mf.a' instruction. For other platforms, mmiob() may have to read
- * a chipset register to ensure ordering.
- *
- * On SN1, we wait for the PIO_WRITE_STATUS Bedrock register to clear.
- */
-void
-sn1_mmiob (void)
-{
- (volatile unsigned long) (*pda.bedrock_rev_id);
- while (!(volatile unsigned long) (*pda.pio_write_status_addr))
- udelay(5);
-}
diff --git a/arch/ia64/sn/kernel/sn1/sn1_smp.c b/arch/ia64/sn/kernel/sn1/sn1_smp.c
deleted file mode 100644
index e24f97eba6576..0000000000000
--- a/arch/ia64/sn/kernel/sn1/sn1_smp.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * SN1 Platform specific SMP Support
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mmzone.h>
-
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/sal.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/hw_irq.h>
-#include <asm/current.h>
-#include <asm/delay.h>
-#include <asm/sn/sn_cpuid.h>
-
-/*
- * The following structure is used to pass params thru smp_call_function
- * to other cpus for flushing TLB ranges.
- */
-typedef struct {
- union {
- struct {
- unsigned long start;
- unsigned long end;
- unsigned long nbits;
- unsigned int rid;
- atomic_t unfinished_count;
- } ptc;
- char pad[SMP_CACHE_BYTES];
- };
-} ptc_params_t;
-
-#define NUMPTC 512
-
-static ptc_params_t ptcParamArray[NUMPTC] __attribute__((__aligned__(128)));
-
-/* use separate cache lines on ptcParamsNextByCpu to avoid false sharing */
-static ptc_params_t *ptcParamsNextByCpu[NR_CPUS*16] __attribute__((__aligned__(128)));
-static volatile ptc_params_t *ptcParamsEmpty __cacheline_aligned;
-
-/*REFERENCED*/
-static spinlock_t ptcParamsLock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
-
-static int ptcInit = 0;
-#ifdef PTCDEBUG
-static int ptcParamsAllBusy = 0; /* debugging/statistics */
-static int ptcCountBacklog = 0;
-static int ptcBacklog[NUMPTC+1];
-static char ptcParamsCounts[NR_CPUS][NUMPTC] __attribute__((__aligned__(128)));
-static char ptcParamsResults[NR_CPUS][NUMPTC] __attribute__((__aligned__(128)));
-#endif
-
-/*
- * Make smp_send_flush_tlbsmp_send_flush_tlb() a weak reference,
- * so that we get a clean compile with the ia64 patch without the
- * actual SN1 specific code in arch/ia64/kernel/smp.c.
- */
-extern void smp_send_flush_tlb (void) __attribute((weak));
-
-/*
- * The following table/struct is for remembering PTC coherency domains. It
- * is also used to translate sapicid into cpuids. We don't want to start
- * cpus unless we know their cache domain.
- */
-#ifdef PTC_NOTYET
-sn_sapicid_info_t sn_sapicid_info[NR_CPUS];
-#endif
-
-/**
- * sn1_ptc_l_range - purge local translation cache
- * @start: start of virtual address range
- * @end: end of virtual address range
- * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
- *
- * Purges the range specified from the local processor's translation cache
- * (as opposed to the translation registers). Note that more than the specified
- * range *may* be cleared from the cache by some processors.
- *
- * This is probably not good enough, but I don't want to try to make it better
- * until I get some statistics on a running system. At a minimum, we should only
- * send IPIs to 1 processor in each TLB domain & have it issue a ptc.g on it's
- * own FSB. Also, we only have to serialize per FSB, not globally.
- *
- * More likely, we will have to do some work to reduce the frequency of calls to
- * this routine.
- */
-static inline void
-sn1_ptc_l_range(unsigned long start, unsigned long end, unsigned long nbits)
-{
- do {
- __asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
- start += (1UL << nbits);
- } while (start < end);
- ia64_srlz_d();
-}
-
-/**
- * sn1_received_flush_tlb - cpu tlb flush routine
- *
- * Flushes the TLB of a given processor.
- */
-void
-sn1_received_flush_tlb(void)
-{
- unsigned long start, end, nbits;
- unsigned int rid, saved_rid;
- int cpu = smp_processor_id();
- int result;
- ptc_params_t *ptcParams;
-
- ptcParams = ptcParamsNextByCpu[cpu*16];
- if (ptcParams == ptcParamsEmpty)
- return;
-
- do {
- start = ptcParams->ptc.start;
- saved_rid = (unsigned int) ia64_get_rr(start);
- end = ptcParams->ptc.end;
- nbits = ptcParams->ptc.nbits;
- rid = ptcParams->ptc.rid;
-
- if (saved_rid != rid) {
- ia64_set_rr(start, (unsigned long)rid);
- ia64_srlz_d();
- }
-
- sn1_ptc_l_range(start, end, nbits);
-
- if (saved_rid != rid)
- ia64_set_rr(start, (unsigned long)saved_rid);
-
- ia64_srlz_i();
-
- result = atomic_dec(&ptcParams->ptc.unfinished_count);
-#ifdef PTCDEBUG
- {
- int i = ptcParams-&ptcParamArray[0];
- ptcParamsResults[cpu][i] = (char) result;
- ptcParamsCounts[cpu][i]++;
- }
-#endif /* PTCDEBUG */
-
- if (++ptcParams == &ptcParamArray[NUMPTC])
- ptcParams = &ptcParamArray[0];
-
- } while (ptcParams != ptcParamsEmpty);
-
- ptcParamsNextByCpu[cpu*16] = ptcParams;
-}
-
-/**
- * sn1_global_tlb_purge - flush a translation cache range on all processors
- * @start: start of virtual address range to flush
- * @end: end of virtual address range
- * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
- *
- * Flushes the translation cache of all processors from @start to @end.
- */
-void
-sn1_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
-{
- ptc_params_t *params;
- ptc_params_t *next;
- unsigned long irqflags;
-#ifdef PTCDEBUG
- ptc_params_t *nextnext;
- int backlog = 0;
-#endif
-
- if (smp_num_cpus == 1) {
- sn1_ptc_l_range(start, end, nbits);
- return;
- }
-
- if (in_interrupt()) {
- /*
- * If at interrupt level and cannot get spinlock,
- * then do something useful by flushing own tlbflush queue
- * so as to avoid a possible deadlock.
- */
- while (!spin_trylock(&ptcParamsLock)) {
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
- udelay(10); /* take it easier on the bus */
- }
- } else {
- spin_lock(&ptcParamsLock);
- }
-
- if (!ptcInit) {
- int cpu;
- ptcInit = 1;
- memset(ptcParamArray, 0, sizeof(ptcParamArray));
- ptcParamsEmpty = &ptcParamArray[0];
- for (cpu=0; cpu<NR_CPUS; cpu++)
- ptcParamsNextByCpu[cpu*16] = &ptcParamArray[0];
-
-#ifdef PTCDEBUG
- memset(ptcBacklog, 0, sizeof(ptcBacklog));
- memset(ptcParamsCounts, 0, sizeof(ptcParamsCounts));
- memset(ptcParamsResults, 0, sizeof(ptcParamsResults));
-#endif /* PTCDEBUG */
- }
-
- params = (ptc_params_t *) ptcParamsEmpty;
- next = (ptc_params_t *) ptcParamsEmpty + 1;
- if (next == &ptcParamArray[NUMPTC])
- next = &ptcParamArray[0];
-
-#ifdef PTCDEBUG
- nextnext = next + 1;
- if (nextnext == &ptcParamArray[NUMPTC])
- nextnext = &ptcParamArray[0];
-
- if (ptcCountBacklog) {
- /* quick count of backlog */
- ptc_params_t *ptr;
-
- /* check the current pointer to the beginning */
- ptr = params;
- while(--ptr >= &ptcParamArray[0]) {
- if (atomic_read(&ptr->ptc.unfinished_count) == 0)
- break;
- ++backlog;
- }
-
- if (backlog) {
- /* check the end of the array */
- ptr = &ptcParamArray[NUMPTC];
- while (--ptr > params) {
- if (atomic_read(&ptr->ptc.unfinished_count) == 0)
- break;
- ++backlog;
- }
- }
- ptcBacklog[backlog]++;
- }
-#endif /* PTCDEBUG */
-
- /* wait for the next entry to clear...should be rare */
- if (atomic_read(&next->ptc.unfinished_count) > 0) {
-#ifdef PTCDEBUG
- ptcParamsAllBusy++;
-
- if (atomic_read(&nextnext->ptc.unfinished_count) == 0) {
- if (atomic_read(&next->ptc.unfinished_count) > 0) {
- panic("\nnonzero next zero nextnext %lx %lx\n",
- (long)next, (long)nextnext);
- }
- }
-#endif
-
- /* it could be this cpu that is behind */
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
-
- /* now we know it's not this cpu, so just wait */
- while (atomic_read(&next->ptc.unfinished_count) > 0) {
- barrier();
- }
- }
-
- params->ptc.start = start;
- params->ptc.end = end;
- params->ptc.nbits = nbits;
- params->ptc.rid = (unsigned int) ia64_get_rr(start);
- atomic_set(&params->ptc.unfinished_count, smp_num_cpus);
-
- /* The atomic_set above can hit memory *after* the update
- * to ptcParamsEmpty below, which opens a timing window
- * that other cpus can squeeze into!
- */
- mb();
-
- /* everything is ready to process:
- * -- global lock is held
- * -- new entry + 1 is free
- * -- new entry is set up
- * so now:
- * -- update the global next pointer
- * -- unlock the global lock
- * -- send IPI to notify other cpus
- * -- process the data ourselves
- */
- ptcParamsEmpty = next;
- spin_unlock(&ptcParamsLock);
- smp_send_flush_tlb();
-
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
-
- /* Currently we don't think global TLB purges need to be atomic.
- * All CPUs get sent IPIs, so if they haven't done the purge,
- * they're busy with interrupts that are at the IPI level, which is
- * priority 15. We're asserting that any code at that level
- * shouldn't be using user TLB entries. To change this to wait
- * for all the flushes to complete, enable the following code.
- */
-#if defined(SN1_SYNCHRONOUS_GLOBAL_TLB_PURGE) || defined(BUS_INT_WAR)
- /* this code is not tested */
- /* wait for the flush to complete */
- while (atomic_read(&params->ptc.unfinished_count) > 0)
- barrier();
-#endif
-}
-
-/**
- * sn_send_IPI_phys - send an IPI to a Nasid and slice
- * @physid: physical cpuid to receive the interrupt.
- * @vector: command to send
- * @delivery_mode: delivery mechanism
- *
- * Sends an IPI (interprocessor interrupt) to the processor specified by
- * @physid
- *
- * @delivery_mode can be one of the following
- *
- * %IA64_IPI_DM_INT - pend an interrupt
- * %IA64_IPI_DM_PMI - pend a PMI
- * %IA64_IPI_DM_NMI - pend an NMI
- * %IA64_IPI_DM_INIT - pend an INIT interrupt
- */
-void
-sn_send_IPI_phys(long physid, int vector, int delivery_mode)
-{
- long *p;
- long nasid, slice;
-
- static int off[4] = {0x1800080, 0x1800088, 0x1a00080, 0x1a00088};
-
-#ifdef BUS_INT_WAR
- if (vector != ap_wakeup_vector) {
- return;
- }
-#endif
-
- nasid = cpu_physical_id_to_nasid(physid);
- slice = cpu_physical_id_to_slice(physid);
-
- p = (long*)(0xc0000a0000000000LL | (nasid<<33) | off[slice]);
-
- mb();
- *p = (delivery_mode << 8) | (vector & 0xff);
-}
-
-
-/**
- * sn1_send_IPI - send an IPI to a processor
- * @cpuid: target of the IPI
- * @vector: command to send
- * @delivery_mode: delivery mechanism
- * @redirect: redirect the IPI?
- *
- * Sends an IPI (interprocessor interrupt) to the processor specified by
- * @cpuid. @delivery_mode can be one of the following
- *
- * %IA64_IPI_DM_INT - pend an interrupt
- * %IA64_IPI_DM_PMI - pend a PMI
- * %IA64_IPI_DM_NMI - pend an NMI
- * %IA64_IPI_DM_INIT - pend an INIT interrupt
- */
-void
-sn1_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
-{
- long physid;
-
- physid = cpu_physical_id(cpuid);
-
- sn_send_IPI_phys(physid, vector, delivery_mode);
-}
-#ifdef CONFIG_SMP
-
-#ifdef PTC_NOTYET
-static void __init
-process_sal_ptc_domain_info(ia64_sal_ptc_domain_info_t *di, int domain)
-{
- ia64_sal_ptc_domain_proc_entry_t *pe;
- int i, sapicid, cpuid;
-
- pe = __va(di->proc_list);
- for (i=0; i<di->proc_count; i++, pe++) {
- sapicid = id_eid_to_sapicid(pe->id, pe->eid);
- cpuid = cpu_logical_id(sapicid);
- sn_sapicid_info[cpuid].domain = domain;
- sn_sapicid_info[cpuid].sapicid = sapicid;
- }
-}
-
-
-static void __init
-process_sal_desc_ptc(ia64_sal_desc_ptc_t *ptc)
-{
- ia64_sal_ptc_domain_info_t *di;
- int i;
-
- di = __va(ptc->domain_info);
- for (i=0; i<ptc->num_domains; i++, di++) {
- process_sal_ptc_domain_info(di, i);
- }
-}
-#endif /* PTC_NOTYET */
-
-/**
- * init_sn1_smp_config - setup PTC domains per processor
- */
-void __init
-init_sn1_smp_config(void)
-{
- if (!ia64_ptc_domain_info) {
- printk("SMP: Can't find PTC domain info. Forcing UP mode\n");
- smp_num_cpus = 1;
- return;
- }
-
-#ifdef PTC_NOTYET
- memset (sn_sapicid_info, -1, sizeof(sn_sapicid_info));
- process_sal_desc_ptc(ia64_ptc_domain_info);
-#endif
-}
-
-#else /* CONFIG_SMP */
-
-void __init
-init_sn1_smp_config(void)
-{
-
-#ifdef PTC_NOTYET
- sn_sapicid_info[0].sapicid = hard_smp_processor_id();
-#endif
-}
-
-#endif /* CONFIG_SMP */
diff --git a/arch/ia64/sn/kernel/sn1/synergy.c b/arch/ia64/sn/kernel/sn1/synergy.c
deleted file mode 100644
index df31731bc73b9..0000000000000
--- a/arch/ia64/sn/kernel/sn1/synergy.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * SN1 Platform specific synergy Support
- *
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/proc_fs.h>
-
-#include <asm/ptrace.h>
-#include <linux/devfs_fs_kernel.h>
-#include <asm/smp.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/sn1/bedrock.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/sn1/synergy.h>
-#include <asm/sn/sndrv.h>
-
-int bit_pos_to_irq(int bit);
-void setclear_mask_b(int irq, int cpuid, int set);
-void setclear_mask_a(int irq, int cpuid, int set);
-void * kmalloc(size_t size, int flags);
-
-static int synergy_perf_initialized = 0;
-
-void
-synergy_intr_alloc(int bit, int cpuid) {
- return;
-}
-
-int
-synergy_intr_connect(int bit,
- int cpuid)
-{
- int irq;
- unsigned is_b;
-
- irq = bit_pos_to_irq(bit);
-
- is_b = (cpuid_to_slice(cpuid)) & 1;
- if (is_b) {
- setclear_mask_b(irq,cpuid,1);
- setclear_mask_a(irq,cpuid, 0);
- } else {
- setclear_mask_a(irq, cpuid, 1);
- setclear_mask_b(irq, cpuid, 0);
- }
- return 0;
-}
-void
-setclear_mask_a(int irq, int cpuid, int set)
-{
- int synergy;
- int nasid;
- int reg_num;
- unsigned long mask;
- unsigned long addr;
- unsigned long reg;
- unsigned long val;
- int my_cnode, my_synergy;
- int target_cnode, target_synergy;
-
- /*
- * Perform some idiot checks ..
- */
- if ( (irq < 0) || (irq > 255) ||
- (cpuid < 0) || (cpuid > 512) ) {
- printk("clear_mask_a: Invalid parameter irq %d cpuid %d\n", irq, cpuid);
- return;
- }
-
- target_cnode = cpuid_to_cnodeid(cpuid);
- target_synergy = cpuid_to_synergy(cpuid);
- my_cnode = cpuid_to_cnodeid(smp_processor_id());
- my_synergy = cpuid_to_synergy(smp_processor_id());
-
- reg_num = irq / 64;
- mask = 1;
- mask <<= (irq % 64);
- switch (reg_num) {
- case 0:
- reg = VEC_MASK0A;
- addr = VEC_MASK0A_ADDR;
- break;
- case 1:
- reg = VEC_MASK1A;
- addr = VEC_MASK1A_ADDR;
- break;
- case 2:
- reg = VEC_MASK2A;
- addr = VEC_MASK2A_ADDR;
- break;
- case 3:
- reg = VEC_MASK3A;
- addr = VEC_MASK3A_ADDR;
- break;
- default:
- reg = addr = 0;
- break;
- }
- if (my_cnode == target_cnode && my_synergy == target_synergy) {
- // local synergy
- val = READ_LOCAL_SYNERGY_REG(addr);
- if (set) {
- val |= mask;
- } else {
- val &= ~mask;
- }
- WRITE_LOCAL_SYNERGY_REG(addr, val);
- val = READ_LOCAL_SYNERGY_REG(addr);
- } else { /* remote synergy */
- synergy = cpuid_to_synergy(cpuid);
- nasid = cpuid_to_nasid(cpuid);
- val = REMOTE_SYNERGY_LOAD(nasid, synergy, reg);
- if (set) {
- val |= mask;
- } else {
- val &= ~mask;
- }
- REMOTE_SYNERGY_STORE(nasid, synergy, reg, val);
- }
-}
-
-void
-setclear_mask_b(int irq, int cpuid, int set)
-{
- int synergy;
- int nasid;
- int reg_num;
- unsigned long mask;
- unsigned long addr;
- unsigned long reg;
- unsigned long val;
- int my_cnode, my_synergy;
- int target_cnode, target_synergy;
-
- /*
- * Perform some idiot checks ..
- */
- if ( (irq < 0) || (irq > 255) ||
- (cpuid < 0) || (cpuid > 512) ) {
- printk("clear_mask_b: Invalid parameter irq %d cpuid %d\n", irq, cpuid);
- return;
- }
-
- target_cnode = cpuid_to_cnodeid(cpuid);
- target_synergy = cpuid_to_synergy(cpuid);
- my_cnode = cpuid_to_cnodeid(smp_processor_id());
- my_synergy = cpuid_to_synergy(smp_processor_id());
-
- reg_num = irq / 64;
- mask = 1;
- mask <<= (irq % 64);
- switch (reg_num) {
- case 0:
- reg = VEC_MASK0B;
- addr = VEC_MASK0B_ADDR;
- break;
- case 1:
- reg = VEC_MASK1B;
- addr = VEC_MASK1B_ADDR;
- break;
- case 2:
- reg = VEC_MASK2B;
- addr = VEC_MASK2B_ADDR;
- break;
- case 3:
- reg = VEC_MASK3B;
- addr = VEC_MASK3B_ADDR;
- break;
- default:
- reg = addr = 0;
- break;
- }
- if (my_cnode == target_cnode && my_synergy == target_synergy) {
- // local synergy
- val = READ_LOCAL_SYNERGY_REG(addr);
- if (set) {
- val |= mask;
- } else {
- val &= ~mask;
- }
- WRITE_LOCAL_SYNERGY_REG(addr, val);
- val = READ_LOCAL_SYNERGY_REG(addr);
- } else { /* remote synergy */
- synergy = cpuid_to_synergy(cpuid);
- nasid = cpuid_to_nasid(cpuid);
- val = REMOTE_SYNERGY_LOAD(nasid, synergy, reg);
- if (set) {
- val |= mask;
- } else {
- val &= ~mask;
- }
- REMOTE_SYNERGY_STORE(nasid, synergy, reg, val);
- }
-}
-
-/*
- * Synergy perf stats. Multiplexed via timer_interrupt.
- */
-
-static int
-synergy_perf_append(uint64_t modesel)
-{
- int cnode;
- nodepda_t *npdap;
- synergy_perf_t *p;
- int checked = 0;
- int err = 0;
- unsigned long flags;
-
- /* bit 45 is enable */
- modesel |= (1UL << 45);
-
- for (cnode=0; cnode < numnodes; cnode++) {
- /* for each node, insert a new synergy_perf entry */
- if ((npdap = NODEPDA(cnode)) == NULL) {
- printk("synergy_perf_append: cnode=%d NODEPDA(cnode)==NULL, nodepda=%p\n", cnode, (void *)nodepda);
- continue;
- }
-
- if (npdap->synergy_perf_enabled) {
- /* user must disable counting to append new events */
- err = -EBUSY;
- break;
- }
-
- if (!checked && npdap->synergy_perf_data != NULL) {
- checked = 1;
- for (p = npdap->synergy_perf_first; ;) {
- if (p->modesel == modesel)
- return 0; /* event already registered */
- if ((p = p->next) == npdap->synergy_perf_first)
- break;
- }
- }
-
- /* XX use kmem_alloc_node() when it is implemented */
- p = (synergy_perf_t *)kmalloc(sizeof(synergy_perf_t), GFP_KERNEL);
- if ((((uint64_t)p) & 7UL) != 0)
- BUG(); /* bad alignment */
- if (p == NULL) {
- err = -ENOMEM;
- break;
- }
- else {
- memset(p, 0, sizeof(synergy_perf_t));
- p->modesel = modesel;
-
- spin_lock_irqsave(&npdap->synergy_perf_lock, flags);
- if (npdap->synergy_perf_data == NULL) {
- /* circular list */
- p->next = p;
- npdap->synergy_perf_first = p;
- npdap->synergy_perf_data = p;
- }
- else {
- p->next = npdap->synergy_perf_data->next;
- npdap->synergy_perf_data->next = p;
- }
- spin_unlock_irqrestore(&npdap->synergy_perf_lock, flags);
- }
- }
-
- return err;
-}
-
-static void
-synergy_perf_set_freq(int freq)
-{
- int cnode;
- nodepda_t *npdap;
-
- for (cnode=0; cnode < numnodes; cnode++) {
- if ((npdap = NODEPDA(cnode)) != NULL)
- npdap->synergy_perf_freq = freq;
- }
-}
-
-static void
-synergy_perf_set_enable(int enable)
-{
- int cnode;
- nodepda_t *npdap;
-
- for (cnode=0; cnode < numnodes; cnode++) {
- if ((npdap = NODEPDA(cnode)) != NULL)
- npdap->synergy_perf_enabled = enable;
- }
- printk("NOTICE: synergy perf counting %sabled on all nodes\n", enable ? "en" : "dis");
-}
-
-static int
-synergy_perf_size(nodepda_t *npdap)
-{
- synergy_perf_t *p;
- int n;
-
- if (npdap->synergy_perf_enabled == 0) {
- /* no stats to return */
- return 0;
- }
-
- spin_lock_irq(&npdap->synergy_perf_lock);
- for (n=0, p = npdap->synergy_perf_first; p;) {
- n++;
- p = p->next;
- if (p == npdap->synergy_perf_first)
- break;
- }
- spin_unlock_irq(&npdap->synergy_perf_lock);
-
- /* bytes == n pairs of {event,counter} */
- return n * 2 * sizeof(uint64_t);
-}
-
-static int
-synergy_perf_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int cnode;
- nodepda_t *npdap;
- synergy_perf_t *p;
- int intarg;
- int fsb;
- uint64_t longarg;
- uint64_t *stats;
- int n;
- devfs_handle_t d;
- arbitrary_info_t info;
-
- if ((d = devfs_get_handle_from_inode(inode)) == NULL)
- return -ENODEV;
- info = hwgraph_fastinfo_get(d);
-
- cnode = SYNERGY_PERF_INFO_CNODE(info);
- fsb = SYNERGY_PERF_INFO_FSB(info);
- npdap = NODEPDA(cnode);
-
- switch (cmd) {
- case SNDRV_GET_SYNERGY_VERSION:
- /* return int, version of data structure for SNDRV_GET_SYNERGYINFO */
- intarg = 1; /* version 1 */
- if (copy_to_user((void *)arg, &intarg, sizeof(intarg)))
- return -EFAULT;
- break;
-
- case SNDRV_GET_INFOSIZE:
- /* return int, sizeof buf needed for SYNERGY_PERF_GET_STATS */
- intarg = synergy_perf_size(npdap);
- if (copy_to_user((void *)arg, &intarg, sizeof(intarg)))
- return -EFAULT;
- break;
-
- case SNDRV_GET_SYNERGYINFO:
- /* return array of event/value pairs, this node only */
- if ((intarg = synergy_perf_size(npdap)) <= 0)
- return -ENODATA;
- if ((stats = (uint64_t *)kmalloc(intarg, GFP_KERNEL)) == NULL)
- return -ENOMEM;
- spin_lock_irq(&npdap->synergy_perf_lock);
- for (n=0, p = npdap->synergy_perf_first; p;) {
- stats[n++] = p->modesel;
- if (p->intervals > 0)
- stats[n++] = p->counts[fsb] * p->total_intervals / p->intervals;
- else
- stats[n++] = 0;
- p = p->next;
- if (p == npdap->synergy_perf_first)
- break;
- }
- spin_unlock_irq(&npdap->synergy_perf_lock);
-
- if (copy_to_user((void *)arg, stats, intarg)) {
- kfree(stats);
- return -EFAULT;
- }
-
- kfree(stats);
- break;
-
- case SNDRV_SYNERGY_APPEND:
- /* reads 64bit event, append synergy perf event to all nodes */
- if (copy_from_user(&longarg, (void *)arg, sizeof(longarg)))
- return -EFAULT;
- return synergy_perf_append(longarg);
- break;
-
- case SNDRV_GET_SYNERGY_STATUS:
- /* return int, 1 if enabled else 0 */
- intarg = npdap->synergy_perf_enabled;
- if (copy_to_user((void *)arg, &intarg, sizeof(intarg)))
- return -EFAULT;
- break;
-
- case SNDRV_SYNERGY_ENABLE:
- /* read int, if true enable counting else disable */
- if (copy_from_user(&intarg, (void *)arg, sizeof(intarg)))
- return -EFAULT;
- synergy_perf_set_enable(intarg);
- break;
-
- case SNDRV_SYNERGY_FREQ:
- /* read int, set jiffies per update */
- if (copy_from_user(&intarg, (void *)arg, sizeof(intarg)))
- return -EFAULT;
- if (intarg < 0 || intarg >= HZ)
- return -EINVAL;
- synergy_perf_set_freq(intarg);
- break;
-
- default:
- printk("Warning: invalid ioctl %d on synergy mon for cnode=%d fsb=%d\n", cmd, cnode, fsb);
- return -EINVAL;
- }
- return(0);
-}
-
-struct file_operations synergy_mon_fops = {
- .ioctl = synergy_perf_ioctl,
-};
-
-void
-synergy_perf_update(int cpu)
-{
- nasid_t nasid;
- cnodeid_t cnode;
- struct nodepda_s *npdap;
-
- /*
- * synergy_perf_initialized is set by synergy_perf_init()
- * which is called last thing by sn_mp_setup(), i.e. well
- * after nodepda has been initialized.
- */
- if (!synergy_perf_initialized)
- return;
-
- cnode = cpuid_to_cnodeid(cpu);
- npdap = NODEPDA(cnode);
-
- if (npdap == NULL || cnode < 0 || cnode >= numnodes)
- /* this should not happen: still in early io init */
- return;
-
-#if 0
- /* use this to check nodepda initialization */
- if (((uint64_t)npdap) & 0x7) {
- printk("\nERROR on cpu %d : cnode=%d, npdap == %p, not aligned\n", cpu, cnode, npdap);
- BUG();
- }
-#endif
-
- if (npdap->synergy_perf_enabled == 0 || npdap->synergy_perf_data == NULL) {
- /* Not enabled, or no events to monitor */
- return;
- }
-
- if (npdap->synergy_inactive_intervals++ % npdap->synergy_perf_freq != 0) {
- /* don't multiplex on every timer interrupt */
- return;
- }
-
- /*
- * Read registers for last interval and increment counters.
- * Hold the per-node synergy_perf_lock so concurrent readers get
- * consistent values.
- */
- spin_lock_irq(&npdap->synergy_perf_lock);
-
- nasid = cpuid_to_nasid(cpu);
- npdap->synergy_active_intervals++;
- npdap->synergy_perf_data->intervals++;
- npdap->synergy_perf_data->total_intervals = npdap->synergy_active_intervals;
-
- npdap->synergy_perf_data->counts[0] += 0xffffffffffUL &
- REMOTE_SYNERGY_LOAD(nasid, 0, PERF_CNTR0_A);
-
- npdap->synergy_perf_data->counts[1] += 0xffffffffffUL &
- REMOTE_SYNERGY_LOAD(nasid, 1, PERF_CNTR0_B);
-
- /* skip to next in circular list */
- npdap->synergy_perf_data = npdap->synergy_perf_data->next;
-
- spin_unlock_irq(&npdap->synergy_perf_lock);
-
- /* set the counter 0 selection modes for both A and B */
- REMOTE_SYNERGY_STORE(nasid, 0, PERF_CNTL0_A, npdap->synergy_perf_data->modesel);
- REMOTE_SYNERGY_STORE(nasid, 1, PERF_CNTL0_B, npdap->synergy_perf_data->modesel);
-
- /* and reset the counter registers to zero */
- REMOTE_SYNERGY_STORE(nasid, 0, PERF_CNTR0_A, 0UL);
- REMOTE_SYNERGY_STORE(nasid, 1, PERF_CNTR0_B, 0UL);
-}
-
-void
-synergy_perf_init(void)
-{
- printk("synergy_perf_init(), counting is initially disabled\n");
- synergy_perf_initialized++;
-}
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 7309c25496613..a56bcb1e6cf5d 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -11,4 +11,5 @@
EXTRA_CFLAGS := -DLITTLE_ENDIAN
-obj-y += cache.o iomv.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o timer.o
+obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
+ prominfo_proc.o timer.o
diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c
index af59e0fe3ddcd..f0cce9edc53d1 100644
--- a/arch/ia64/sn/kernel/sn2/cache.c
+++ b/arch/ia64/sn/kernel/sn2/cache.c
@@ -4,7 +4,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
*
*/
@@ -24,6 +24,5 @@ void
sn_flush_all_caches(long flush_addr, long bytes)
{
flush_icache_range(flush_addr, flush_addr+bytes);
+ mb();
}
-
-
diff --git a/arch/ia64/sn/kernel/sn2/io.c b/arch/ia64/sn/kernel/sn2/io.c
index 9de12763a35f0..59423708d30ce 100644
--- a/arch/ia64/sn/kernel/sn2/io.c
+++ b/arch/ia64/sn/kernel/sn2/io.c
@@ -9,13 +9,8 @@
* we wrap the inlines from asm/ia64/sn/sn2/io.h here.
*/
-#include <linux/config.h>
-#include <linux/types.h>
-
#include <asm/sn/sn2/io.h>
-#ifdef CONFIG_IA64_GENERIC
-
unsigned int
sn_inb (unsigned long port)
{
@@ -73,7 +68,7 @@ sn_readl (void *addr)
unsigned long
sn_readq (void *addr)
{
- return __sn_readq (addr)
+ return __sn_readq (addr);
}
@@ -94,5 +89,3 @@ asm ("__sn_readb = sn_readb");
asm ("__sn_readw = sn_readw");
asm ("__sn_readl = sn_readl");
asm ("__sn_readq = sn_readq");
-
-#endif /* CONFIG_IA64_GENERIC */
diff --git a/arch/ia64/sn/kernel/sn2/iomv.c b/arch/ia64/sn/kernel/sn2/iomv.c
deleted file mode 100644
index 4dd53594f5c07..0000000000000
--- a/arch/ia64/sn/kernel/sn2/iomv.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/sn_cpuid.h>
-
-/**
- * sn_io_addr - convert an in/out port to an i/o address
- * @port: port to convert
- *
- * Legacy in/out instructions are converted to ld/st instructions
- * on IA64. This routine will convert a port number into a valid
- * SN i/o address. Used by sn_in*() and sn_out*().
- */
-void *
-sn_io_addr(unsigned long port)
-{
- if (!IS_RUNNING_ON_SIMULATOR()) {
- return( (void *) (port | __IA64_UNCACHED_OFFSET));
- } else {
- unsigned long io_base;
- unsigned long addr;
-
- /*
- * word align port, but need more than 10 bits
- * for accessing registers in bedrock local block
- * (so we don't do port&0xfff)
- */
- if ((port >= 0x1f0 && port <= 0x1f7) ||
- port == 0x3f6 || port == 0x3f7) {
- io_base = (0xc000000fcc000000 | ((unsigned long)get_nasid() << 38));
- addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
- } else {
- addr = __ia64_get_io_port_base() | ((port >> 2) << 2);
- }
- return(void *) addr;
- }
-}
-
-EXPORT_SYMBOL(sn_io_addr);
-
-/**
- * sn_mmiob - I/O space memory barrier
- *
- * Acts as a memory mapped I/O barrier for platforms that queue writes to
- * I/O space. This ensures that subsequent writes to I/O space arrive after
- * all previous writes. For most ia64 platforms, this is a simple
- * 'mf.a' instruction. For other platforms, mmiob() may have to read
- * a chipset register to ensure ordering.
- *
- * On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear.
- * See PV 871084 for details about the WAR about zero value.
- *
- */
-void
-sn_mmiob (void)
-{
- while ((((volatile unsigned long) (*pda.pio_write_status_addr)) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) !=
- SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK)
- udelay(1);
-}
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
new file mode 100644
index 0000000000000..f860679d5b12f
--- /dev/null
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
@@ -0,0 +1,361 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Module to export the system's Firmware Interface Tables, including
+ * PROM revision numbers, in /proc
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <asm/io.h>
+#include <asm/sn/simulator.h>
+
+/* to lookup nasids */
+#include <asm/sn/sn_cpuid.h>
+
+MODULE_DESCRIPTION("PROM version reporting for /proc");
+MODULE_AUTHOR("Chad Talbott");
+MODULE_LICENSE("GPL");
+
+#undef DEBUG_PROMINFO
+
+#define TRACE_PROMINFO
+
+#if defined(DEBUG_PROMINFO)
+# define DPRINTK(x...) printk(KERN_DEBUG x)
+#else
+# define DPRINTK(x...)
+#endif
+
+#if defined(TRACE_PROMINFO) && defined(DEBUG_PROMINFO)
+# if defined(__GNUC__)
+# define TRACE() printk(KERN_DEBUG "%s:%d:%s\n", \
+ __FILE__, __LINE__, __FUNCTION__)
+# else
+# define TRACE() printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__)
+# endif
+#else
+# define TRACE()
+#endif
+
+/* Sub-regions determined by bits in Node Offset */
+#define LB_PROM_SPACE 0x0000000700000000ul /* Local LB PROM */
+
+#define FIT_SIGNATURE 0x2020205f5449465ful
+/* Standard Intel FIT entry types */
+#define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */
+#define FIT_ENTRY_PAL_B 0x01 /* PAL_B entry */
+/* Entries 0x02 through 0x0D reserved by Intel */
+#define FIT_ENTRY_PAL_A_PROC 0x0E /* Processor-specific PAL_A entry */
+#define FIT_ENTRY_PAL_A 0x0F /* PAL_A entry, same as... */
+#define FIT_ENTRY_PAL_A_GEN 0x0F /* ...Generic PAL_A entry */
+#define FIT_ENTRY_UNUSED 0x7F /* Unused (reserved by Intel?) */
+/* OEM-defined entries range from 0x10 to 0x7E. */
+#define FIT_ENTRY_SAL_A 0x10 /* SAL_A entry */
+#define FIT_ENTRY_SAL_B 0x11 /* SAL_B entry */
+#define FIT_ENTRY_SALRUNTIME 0x12 /* SAL runtime entry */
+#define FIT_ENTRY_EFI 0x1F /* EFI entry */
+#define FIT_ENTRY_FPSWA 0x20 /* embedded fpswa entry */
+#define FIT_ENTRY_VMLINUX 0x21 /* embedded vmlinux entry */
+
+#define FIT_MAJOR_SHIFT (32 + 8)
+#define FIT_MAJOR_MASK ((1 << 8) - 1)
+#define FIT_MINOR_SHIFT 32
+#define FIT_MINOR_MASK ((1 << 8) - 1)
+
+#define FIT_MAJOR(q) \
+ ((unsigned) ((q) >> FIT_MAJOR_SHIFT) & FIT_MAJOR_MASK)
+#define FIT_MINOR(q) \
+ ((unsigned) ((q) >> FIT_MINOR_SHIFT) & FIT_MINOR_MASK)
+
+#define FIT_TYPE_SHIFT (32 + 16)
+#define FIT_TYPE_MASK ((1 << 7) - 1)
+
+#define FIT_TYPE(q) \
+ ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
+
+#define FIT_ENTRY(type, maj, min, size) \
+ ((((unsigned long)(maj) & FIT_MAJOR_MASK) << FIT_MAJOR_SHIFT) | \
+ (((unsigned long)(min) & FIT_MINOR_MASK) << FIT_MINOR_SHIFT) | \
+ (((unsigned long)(type) & FIT_TYPE_MASK) << FIT_TYPE_SHIFT) | \
+ (size))
+
+struct fit_type_map_t {
+ unsigned char type;
+ const char *name;
+};
+
+static const struct fit_type_map_t fit_entry_types[] = {
+ { FIT_ENTRY_FIT_HEADER, "FIT Header" },
+ { FIT_ENTRY_PAL_A_GEN, "Generic PAL_A" },
+ { FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A" },
+ { FIT_ENTRY_PAL_A, "PAL_A" },
+ { FIT_ENTRY_PAL_B, "PAL_B" },
+ { FIT_ENTRY_SAL_A, "SAL_A" },
+ { FIT_ENTRY_SAL_B, "SAL_B" },
+ { FIT_ENTRY_SALRUNTIME, "SAL runtime" },
+ { FIT_ENTRY_EFI, "EFI" },
+ { FIT_ENTRY_VMLINUX, "Embedded Linux" },
+ { FIT_ENTRY_FPSWA, "Embedded FPSWA" },
+ { FIT_ENTRY_UNUSED, "Unused" },
+ { 0xff, "Error" },
+};
+
+static const char *
+fit_type_name(unsigned char type)
+{
+ struct fit_type_map_t const*mapp;
+
+ for (mapp = fit_entry_types; mapp->type != 0xff; mapp++)
+ if (type == mapp->type)
+ return mapp->name;
+
+ if ((type > FIT_ENTRY_PAL_A) && (type < FIT_ENTRY_UNUSED))
+ return "OEM type";
+ if ((type > FIT_ENTRY_PAL_B) && (type < FIT_ENTRY_PAL_A))
+ return "Reserved";
+
+ return "Unknown type";
+}
+
+/* These two routines read the FIT table directly from the FLASH PROM
+ * on a specific node. The PROM can only be accessed using aligned 64
+ * bit reads, so we do that and then shift and mask the result to get
+ * at each field.
+ */
+static int
+dump_fit_entry(char *page, unsigned long *fentry)
+{
+ unsigned long q1, q2;
+ unsigned type;
+
+ TRACE();
+
+ q1 = readq(fentry);
+ q2 = readq(fentry + 1);
+ type = FIT_TYPE(q2);
+ return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n",
+ type,
+ fit_type_name(type),
+ FIT_MAJOR(q2), FIT_MINOR(q2),
+ q1,
+ /* mult by sixteen to get size in bytes */
+ (unsigned)q2 * 16);
+}
+
+/* We assume that the fit table will be small enough that we can print
+ * the whole thing into one page. (This is true for our default 16kB
+ * pages -- each entry is about 60 chars wide when printed.) I read
+ * somewhere that the maximum size of the FIT is 128 entries, so we're
+ * OK except for 4kB pages (and no one is going to do that on SN
+ * anyway).
+ */
+static int
+dump_fit(char *page, unsigned long *fit)
+{
+ unsigned long qw;
+ int nentries;
+ int fentry;
+ char *p;
+
+ TRACE();
+
+ DPRINTK("dumping fit from %p\n", (void *)fit);
+
+ qw = readq(fit);
+ DPRINTK("FIT signature: %016lx (%.8s)\n", qw, (char *)&qw);
+ if (qw != FIT_SIGNATURE)
+ printk(KERN_WARNING "Unrecognized FIT signature");
+
+ qw = readq(fit + 1);
+ nentries = (unsigned)qw;
+ DPRINTK("number of fit entries: %u\n", nentries);
+ /* check that we won't overflow the page -- see comment above */
+ BUG_ON(nentries * 60 > PAGE_SIZE);
+
+ p = page;
+ for (fentry = 0; fentry < nentries; fentry++)
+ /* each FIT entry is two 64 bit words */
+ p += dump_fit_entry(p, fit + 2 * fentry);
+
+ return p - page;
+}
+
+static int
+dump_version(char *page, unsigned long *fit)
+{
+ int nentries;
+ int fentry;
+ unsigned long qw;
+
+ TRACE();
+
+ nentries = (unsigned)readq(fit + 1);
+ BUG_ON(nentries * 60 > PAGE_SIZE);
+
+ for (fentry = 0; fentry < nentries; fentry++) {
+ qw = readq(fit + 2 * fentry + 1);
+ if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A)
+ return sprintf(page, "%x.%02x\n",
+ FIT_MAJOR(qw), FIT_MINOR(qw));
+ }
+ return 0;
+}
+
+/* same as in proc_misc.c */
+static int
+proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof,
+ int len)
+{
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+
+static int
+read_version_entry(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
+{
+ int len = 0;
+
+ MOD_INC_USE_COUNT;
+ /* data holds the pointer to this node's FIT */
+ len = dump_version(page, (unsigned long *)data);
+ len = proc_calc_metrics(page, start, off, count, eof, len);
+ MOD_DEC_USE_COUNT;
+ return len;
+}
+
+static int
+read_fit_entry(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
+{
+ int len = 0;
+
+ MOD_INC_USE_COUNT;
+ /* data holds the pointer to this node's FIT */
+ len = dump_fit(page, (unsigned long *)data);
+ len = proc_calc_metrics(page, start, off, count, eof, len);
+ MOD_DEC_USE_COUNT;
+
+ return len;
+}
+
+/* this is a fake FIT that's used on the medusa simulator which
+ * doesn't usually run a complete PROM.
+ */
+#ifdef CONFIG_IA64_SGI_SN_SIM
+static unsigned long fakefit[] = {
+ /* this is all we need to satisfy the code below */
+ FIT_SIGNATURE,
+ FIT_ENTRY(FIT_ENTRY_FIT_HEADER, 0x02, 0x60, 2),
+ /* dump something arbitrary for
+ * /proc/sgi_prominfo/nodeX/version */
+ 0xbadbeef00fa3ef17ul,
+ FIT_ENTRY(FIT_ENTRY_SAL_A, 0, 0x99, 0x100)
+};
+#endif
+
+static unsigned long *
+lookup_fit(int nasid)
+{
+ unsigned long *fitp;
+ unsigned long fit_paddr;
+ unsigned long *fit_vaddr;
+
+#ifdef CONFIG_IA64_SGI_SN_SIM
+ if (IS_RUNNING_ON_SIMULATOR())
+ return fakefit;
+#endif
+
+ fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
+ DPRINTK("pointer to fit at %p\n", (void *)fitp);
+ fit_paddr = readq(fitp);
+ DPRINTK("fit pointer contains %lx\n", fit_paddr);
+ /* snag just the node-relative offset */
+ fit_paddr &= ~0ul >> (63-35);
+ /* the pointer to the FIT is relative to IA-64 compatibility
+ * space. However, the PROM is mapped at a different offset
+ * in MMR space (both local and global)
+ */
+ fit_paddr += 0x700000000;
+ fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr);
+ DPRINTK("fit at %p\n", (void *)fit_vaddr);
+ return fit_vaddr;
+}
+
+/* module entry points */
+int __init prominfo_init(void);
+void __exit prominfo_exit(void);
+
+module_init(prominfo_init);
+module_exit(prominfo_exit);
+
+static struct proc_dir_entry **proc_entries;
+static struct proc_dir_entry *sgi_prominfo_entry;
+
+#define NODE_NAME_LEN 11
+
+int __init
+prominfo_init(void)
+{
+ struct proc_dir_entry **entp;
+ cnodeid_t cnodeid;
+ nasid_t nasid;
+ char name[NODE_NAME_LEN];
+
+ TRACE();
+
+ DPRINTK("running on cpu %d\n", smp_processor_id());
+ DPRINTK("numnodes %d\n", numnodes);
+
+ proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *),
+ GFP_KERNEL);
+
+ sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
+
+ for (cnodeid = 0, entp = proc_entries;
+ cnodeid < numnodes;
+ cnodeid++, entp++) {
+ sprintf(name, "node%d", cnodeid);
+ *entp = proc_mkdir(name, sgi_prominfo_entry);
+ nasid = cnodeid_to_nasid(cnodeid);
+ create_proc_read_entry(
+ "fit", 0, *entp, read_fit_entry,
+ lookup_fit(nasid));
+ create_proc_read_entry(
+ "version", 0, *entp, read_version_entry,
+ lookup_fit(nasid));
+ }
+
+ return 0;
+}
+
+void __exit
+prominfo_exit(void)
+{
+ struct proc_dir_entry **entp;
+ unsigned cnodeid;
+ char name[NODE_NAME_LEN];
+
+ TRACE();
+
+ for (cnodeid = 0, entp = proc_entries;
+ cnodeid < numnodes;
+ cnodeid++, entp++) {
+ remove_proc_entry("fit", *entp);
+ remove_proc_entry("version", *entp);
+ sprintf(name, "node%d", cnodeid);
+ remove_proc_entry(name, sgi_prominfo_entry);
+ }
+ remove_proc_entry("sgi_prominfo", NULL);
+ kfree(proc_entries);
+}
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 1850229970c14..c7116a35e5b14 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -1,7 +1,7 @@
/*
* SN2 Platform specific SMP Support
*
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -79,284 +79,6 @@ wait_piowc(void)
return ws;
}
-#ifdef PTCG_WAR
-/*
- * The following structure is used to pass params thru smp_call_function
- * to other cpus for flushing TLB ranges.
- */
-typedef struct {
- unsigned long start;
- unsigned long end;
- unsigned long nbits;
- unsigned int rid;
- atomic_t unfinished_count;
- char fill[96];
-} ptc_params_t;
-
-#define NUMPTC 512
-
-static ptc_params_t ptcParamArray[NUMPTC] __attribute__((__aligned__(128)));
-
-/* use separate cache lines on ptcParamsNextByCpu to avoid false sharing */
-static ptc_params_t *ptcParamsNextByCpu[NR_CPUS*16] __attribute__((__aligned__(128)));
-static volatile ptc_params_t *ptcParamsEmpty __cacheline_aligned;
-
-/*REFERENCED*/
-static spinlock_t ptcParamsLock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
-
-static int ptcInit = 0;
-#ifdef PTCDEBUG
-static int ptcParamsAllBusy = 0; /* debugging/statistics */
-static int ptcCountBacklog = 0;
-static int ptcBacklog[NUMPTC+1];
-static char ptcParamsCounts[NR_CPUS][NUMPTC] __attribute__((__aligned__(128)));
-static char ptcParamsResults[NR_CPUS][NUMPTC] __attribute__((__aligned__(128)));
-#endif
-
-/*
- * Make smp_send_flush_tlbsmp_send_flush_tlb() a weak reference,
- * so that we get a clean compile with the ia64 patch without the
- * actual SN1 specific code in arch/ia64/kernel/smp.c.
- */
-extern void smp_send_flush_tlb (void) __attribute((weak));
-
-
-/**
- * sn1_ptc_l_range - purge local translation cache
- * @start: start of virtual address range
- * @end: end of virtual address range
- * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
- *
- * Purges the range specified from the local processor's translation cache
- * (as opposed to the translation registers). Note that more than the specified
- * range *may* be cleared from the cache by some processors.
- *
- * This is probably not good enough, but I don't want to try to make it better
- * until I get some statistics on a running system. At a minimum, we should only
- * send IPIs to 1 processor in each TLB domain & have it issue a ptc.g on it's
- * own FSB. Also, we only have to serialize per FSB, not globally.
- *
- * More likely, we will have to do some work to reduce the frequency of calls to
- * this routine.
- */
-static inline void
-sn1_ptc_l_range(unsigned long start, unsigned long end, unsigned long nbits)
-{
- do {
- __asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
- start += (1UL << nbits);
- } while (start < end);
- ia64_srlz_d();
-}
-
-/**
- * sn1_received_flush_tlb - cpu tlb flush routine
- *
- * Flushes the TLB of a given processor.
- */
-void
-sn1_received_flush_tlb(void)
-{
- unsigned long start, end, nbits;
- unsigned int rid, saved_rid;
- int cpu = smp_processor_id();
- int result;
- ptc_params_t *ptcParams;
-
- ptcParams = ptcParamsNextByCpu[cpu*16];
- if (ptcParams == ptcParamsEmpty)
- return;
-
- do {
- start = ptcParams->start;
- saved_rid = (unsigned int) ia64_get_rr(start);
- end = ptcParams->end;
- nbits = ptcParams->nbits;
- rid = ptcParams->rid;
-
- if (saved_rid != rid) {
- ia64_set_rr(start, (unsigned long)rid);
- ia64_srlz_d();
- }
-
- sn1_ptc_l_range(start, end, nbits);
-
- if (saved_rid != rid)
- ia64_set_rr(start, (unsigned long)saved_rid);
-
- ia64_srlz_i();
-
- result = atomic_dec(&ptcParams->unfinished_count);
-#ifdef PTCDEBUG
- {
- int i = ptcParams-&ptcParamArray[0];
- ptcParamsResults[cpu][i] = (char) result;
- ptcParamsCounts[cpu][i]++;
- }
-#endif /* PTCDEBUG */
-
- if (++ptcParams == &ptcParamArray[NUMPTC])
- ptcParams = &ptcParamArray[0];
-
- } while (ptcParams != ptcParamsEmpty);
-
- ptcParamsNextByCpu[cpu*16] = ptcParams;
-}
-
-/**
- * sn1_global_tlb_purge - flush a translation cache range on all processors
- * @start: start of virtual address range to flush
- * @end: end of virtual address range
- * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
- *
- * Flushes the translation cache of all processors from @start to @end.
- */
-void
-sn1_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
-{
- ptc_params_t *params;
- ptc_params_t *next;
- unsigned long irqflags;
-#ifdef PTCDEBUG
- ptc_params_t *nextnext;
- int backlog = 0;
-#endif
-
- if (smp_num_cpus == 1) {
- sn1_ptc_l_range(start, end, nbits);
- return;
- }
-
- if (in_interrupt()) {
- /*
- * If at interrupt level and cannot get spinlock,
- * then do something useful by flushing own tlbflush queue
- * so as to avoid a possible deadlock.
- */
- while (!spin_trylock(&ptcParamsLock)) {
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
- udelay(10); /* take it easier on the bus */
- }
- } else {
- spin_lock(&ptcParamsLock);
- }
-
- if (!ptcInit) {
- int cpu;
- ptcInit = 1;
- memset(ptcParamArray, 0, sizeof(ptcParamArray));
- ptcParamsEmpty = &ptcParamArray[0];
- for (cpu=0; cpu<NR_CPUS; cpu++)
- ptcParamsNextByCpu[cpu*16] = &ptcParamArray[0];
-
-#ifdef PTCDEBUG
- memset(ptcBacklog, 0, sizeof(ptcBacklog));
- memset(ptcParamsCounts, 0, sizeof(ptcParamsCounts));
- memset(ptcParamsResults, 0, sizeof(ptcParamsResults));
-#endif /* PTCDEBUG */
- }
-
- params = (ptc_params_t *) ptcParamsEmpty;
- next = (ptc_params_t *) ptcParamsEmpty + 1;
- if (next == &ptcParamArray[NUMPTC])
- next = &ptcParamArray[0];
-
-#ifdef PTCDEBUG
- nextnext = next + 1;
- if (nextnext == &ptcParamArray[NUMPTC])
- nextnext = &ptcParamArray[0];
-
- if (ptcCountBacklog) {
- /* quick count of backlog */
- ptc_params_t *ptr;
-
- /* check the current pointer to the beginning */
- ptr = params;
- while(--ptr >= &ptcParamArray[0]) {
- if (atomic_read(&ptr->unfinished_count) == 0)
- break;
- ++backlog;
- }
-
- if (backlog) {
- /* check the end of the array */
- ptr = &ptcParamArray[NUMPTC];
- while (--ptr > params) {
- if (atomic_read(&ptr->unfinished_count) == 0)
- break;
- ++backlog;
- }
- }
- ptcBacklog[backlog]++;
- }
-#endif /* PTCDEBUG */
-
- /* wait for the next entry to clear...should be rare */
- if (atomic_read(&next->unfinished_count) > 0) {
-#ifdef PTCDEBUG
- ptcParamsAllBusy++;
-
- if (atomic_read(&nextnext->unfinished_count) == 0) {
- if (atomic_read(&next->unfinished_count) > 0) {
- panic("\nnonzero next zero nextnext %lx %lx\n",
- (long)next, (long)nextnext);
- }
- }
-#endif
-
- /* it could be this cpu that is behind */
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
-
- /* now we know it's not this cpu, so just wait */
- while (atomic_read(&next->unfinished_count) > 0) {
- barrier();
- }
- }
-
- params->start = start;
- params->end = end;
- params->nbits = nbits;
- params->rid = (unsigned int) ia64_get_rr(start);
- atomic_set(&params->unfinished_count, smp_num_cpus);
-
- /* The atomic_set above can hit memory *after* the update
- * to ptcParamsEmpty below, which opens a timing window
- * that other cpus can squeeze into!
- */
- mb();
-
- /* everything is ready to process:
- * -- global lock is held
- * -- new entry + 1 is free
- * -- new entry is set up
- * so now:
- * -- update the global next pointer
- * -- unlock the global lock
- * -- send IPI to notify other cpus
- * -- process the data ourselves
- */
- ptcParamsEmpty = next;
- spin_unlock(&ptcParamsLock);
- smp_send_flush_tlb();
-
- local_irq_save(irqflags);
- sn1_received_flush_tlb();
- local_irq_restore(irqflags);
-
- /*
- * Since IPIs are polled event (for now), we need to wait til the
- * TLB flush has started.
- * wait for the flush to complete
- */
- while (atomic_read(&params->unfinished_count) > 0)
- barrier();
-}
-
-#endif /* PTCG_WAR */
/**
@@ -372,18 +94,10 @@ sn1_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit
void
sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
{
- int cnode, mycnode, nasid;
+ int cnode, mycnode, nasid, flushed=0;
volatile unsigned long *ptc0, *ptc1;
unsigned long flags=0, data0, data1;
- /*
- * Special case 1 cpu & 1 node. Use local purges.
- */
-#ifdef PTCG_WAR
- sn1_global_tlb_purge(start, end, nbits);
- return;
-#endif /* PTCG_WAR */
-
data0 = (1UL<<SH_PTC_0_A_SHFT) |
(nbits<<SH_PTC_0_PS_SHFT) |
((ia64_get_rr(start)>>8)<<SH_PTC_0_RID_SHFT) |
@@ -392,18 +106,9 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit
ptc0 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
ptc1 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
- mycnode = local_nodeid;
-
- /*
- * For now, we don't want to spin uninterruptibly waiting
- * for the lock. Makes hangs hard to debug.
- */
- local_irq_save(flags);
- while (!spin_trylock(&sn2_global_ptc_lock)) {
- local_irq_restore(flags);
- udelay(1);
- local_irq_save(flags);
- }
+ mycnode = numa_node_id();
+
+ spin_lock_irqsave(&sn2_global_ptc_lock, flags);
do {
data1 = start | (1UL<<SH_PTC_1_START_SHFT);
@@ -417,11 +122,13 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit
ptc0 = CHANGE_NASID(nasid, ptc0);
ptc1 = CHANGE_NASID(nasid, ptc1);
pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
+ flushed = 1;
}
}
- if (wait_piowc() & SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK)
+ if (flushed && (wait_piowc() & SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK)) {
sn2_ptc_deadlock_recovery(data0, data1);
+ }
start += (1UL << nbits);
@@ -451,7 +158,7 @@ sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1)
ptc1 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
piows = (long*)pda->pio_write_status_addr;
- mycnode = local_nodeid;
+ mycnode = numa_node_id();
for (cnode = 0; cnode < numnodes; cnode++) {
if (is_headless_node(cnode) || cnode == mycnode)
@@ -482,16 +189,10 @@ sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1)
void
sn_send_IPI_phys(long physid, int vector, int delivery_mode)
{
- long nasid, slice;
- long val;
+ long nasid, slice, val;
+ unsigned long flags=0;
volatile long *p;
-#ifdef BUS_INT_WAR
- if (vector != ap_wakeup_vector && delivery_mode == IA64_IPI_DM_INT) {
- return;
- }
-#endif
-
nasid = cpu_physical_id_to_nasid(physid);
slice = cpu_physical_id_to_slice(physid);
@@ -503,12 +204,15 @@ sn_send_IPI_phys(long physid, int vector, int delivery_mode)
(0x000feeUL<<SH_IPI_INT_BASE_SHFT);
mb();
+ if (enable_shub_wars_1_1() ) {
+ spin_lock_irqsave(&sn2_global_ptc_lock, flags);
+ }
pio_phys_write_mmr(p, val);
+ if (enable_shub_wars_1_1() ) {
+ wait_piowc();
+ spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+ }
-#ifndef CONFIG_SHUB_1_0_SPECIFIC
- /* doesn't work on shub 1.0 */
- wait_piowc();
-#endif
}
/**
@@ -536,4 +240,3 @@ sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
sn_send_IPI_phys(physid, vector, delivery_mode);
}
-
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index 60eefbac4a21e..e7a8987b672d2 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -31,6 +31,7 @@
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
#include <linux/config.h>
+#include <asm/uaccess.h>
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
@@ -43,7 +44,7 @@ static int partition_id_read_proc(char *page, char **start, off_t off,
return sprintf(page, "%d\n", sn_local_partid());
}
-struct proc_dir_entry * sgi_proc_dir = NULL;
+static struct proc_dir_entry * sgi_proc_dir;
void
register_sn_partition_id(void) {
@@ -135,11 +136,60 @@ register_sn_force_interrupt(void) {
entry->write_proc = sn_force_interrupt_write_proc;
}
}
+
+extern int sn_linkstats_get(char *);
+extern int sn_linkstats_reset(unsigned long);
+
+static int
+sn_linkstats_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+
+ return sn_linkstats_get(page);
+}
+
+static int
+sn_linkstats_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char s[64];
+ unsigned long msecs;
+ int e = count;
+
+ if (copy_from_user(s, buffer, count < sizeof(s) ? count : sizeof(s)))
+ e = -EFAULT;
+ else {
+ if (sscanf(s, "%lu", &msecs) != 1 || msecs < 5)
+ /* at least 5 milliseconds between updates */
+ e = -EINVAL;
+ else
+ sn_linkstats_reset(msecs);
+ }
+
+ return e;
+}
+
+void
+register_sn_linkstats(void) {
+ struct proc_dir_entry *entry;
+
+ if (!sgi_proc_dir) {
+ sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+ }
+ entry = create_proc_entry("linkstats", 0444, sgi_proc_dir);
+ if (entry) {
+ entry->nlink = 1;
+ entry->data = 0;
+ entry->read_proc = sn_linkstats_read_proc;
+ entry->write_proc = sn_linkstats_write_proc;
+ }
+}
+
void
register_sn_procfs(void) {
register_sn_partition_id();
register_sn_serial_numbers();
register_sn_force_interrupt();
+ register_sn_linkstats();
}
#endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/sn_asm.S b/arch/ia64/sn/kernel/sn_asm.S
deleted file mode 100644
index 833a399afe96e..0000000000000
--- a/arch/ia64/sn/kernel/sn_asm.S
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/config.h>
-#ifdef CONFIG_IA64_SGI_AUTOTEST
-
-// Testing only.
-// Routine will cause MCAs
-// zzzmca(n)
-// n=0 MCA via duplicate TLB dropin
-// n=1 MCA via read of garbage address
-// n=2 MCA via lfetch read of garbage address
-//
-
-#define ITIR(key, ps) ((key<<8) | (ps<<2))
-#define TLB_PAGESIZE 28 // Use 256MB pages for now.
-
- .global zzzmca
- .proc zzzmca
-zzzmca:
- alloc loc4 = ar.pfs,2,8,1,0;;
- cmp.ne p6,p0=r32,r0;;
- movl r2=0x2dead
- movl r3=0x3dead
- movl r15=0x15dead
- movl r16=0x16dead
- movl r31=0x31dead
- movl loc0=0x34beef
- movl loc1=0x35beef
- movl loc2=0x36beef
- movl loc3=0x37beef
- movl out0=0x42beef
-
- movl r20=0x32feed;;
- mov ar32=r20
- movl r20=0x36feed;;
- mov ar36=r20
- movl r20=0x65feed;;
- mov ar65=r20
- movl r20=0x66feed;;
- mov ar66=r20
-
-(p6) br.cond.sptk 1f
-
- rsm 0x2000;;
- srlz.d;
- mov r11 = 5
- mov r3 = ITIR(0,TLB_PAGESIZE);;
- mov cr.itir = r3
- mov r10 = 0;;
- itr.d dtr[r11] = r10;;
- mov r11 = 6
-
- itr.d dtr[r11] = r10;;
- br 9f
-
-1:
- cmp.eq p6,p7=1,r32
-#ifdef CONFIG_IA64_SGI_SN1
- movl r8=0xe00000fe00000048;;
-#else
- movl r8=0xe0007fb000000048;;
-#endif
- (p6) ld8 r9=[r8]
- (p7) lfetch.fault.nt2 [r8]
- ;;
- mf
- ;;
- mf.a
- ;;
- srlz.d
-
-9: mov ar.pfs=loc4
- br.ret.sptk rp
-
- .endp zzzmca
-
-#endif
diff --git a/arch/ia64/sn/kernel/sn_ksyms.c b/arch/ia64/sn/kernel/sn_ksyms.c
index ec882453610d3..97f3cf5208dbe 100644
--- a/arch/ia64/sn/kernel/sn_ksyms.c
+++ b/arch/ia64/sn/kernel/sn_ksyms.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
@@ -16,11 +16,10 @@
#include <asm/machvec.h>
#include <asm/sn/intr.h>
-#include <asm/sn/arch.h>
#include <linux/mm.h>
-#include <linux/devfs_fs_kernel.h>
-extern devfs_handle_t base_io_scsi_ctlr_vhdl[];
+#include <asm/sn/sgi.h>
+extern vertex_hdl_t base_io_scsi_ctlr_vhdl[];
#include <asm/sn/types.h>
extern cnodeid_t master_node_get(devfs_handle_t vhdl);
#include <asm/sn/arch.h>
@@ -32,9 +31,9 @@ EXPORT_SYMBOL(master_node_get);
* symbols referenced by the PCIBA module
*/
#include <asm/sn/invent.h>
-#include <asm/sn/hack.h>
#include <asm/sn/hcl.h>
#include <asm/sn/pci/pciio.h>
+#include <asm/sn/sn_cpuid.h>
devfs_handle_t
devfn_to_vertex(unsigned char busnum, unsigned int devfn);
@@ -55,29 +54,26 @@ EXPORT_SYMBOL(__va_debug);
EXPORT_SYMBOL(sn_send_IPI_phys);
/* symbols referenced by partitioning modules */
-#include <asm/sn/bte_copy.h>
+#include <asm/sn/bte.h>
+EXPORT_SYMBOL(bte_copy);
EXPORT_SYMBOL(bte_unaligned_copy);
#include <asm/sal.h>
EXPORT_SYMBOL(ia64_sal);
+EXPORT_SYMBOL(physical_node_map);
-#ifdef CONFIG_IA64_SGI_SN2
#include <asm/sn/sn_sal.h>
EXPORT_SYMBOL(sal_lock);
EXPORT_SYMBOL(sn_partid);
EXPORT_SYMBOL(sn_local_partid);
EXPORT_SYMBOL(sn_system_serial_number_string);
EXPORT_SYMBOL(sn_partition_serial_number);
-#endif
+
+EXPORT_SYMBOL(sn_mmiob);
/* added by tduffy 04.08.01 to fix depmod issues */
#include <linux/mmzone.h>
-#ifdef BUS_INT_WAR
-extern void sn_add_polled_interrupt(int, int);
-extern void sn_delete_polled_interrupt(int);
-EXPORT_SYMBOL(sn_add_polled_interrupt);
-EXPORT_SYMBOL(sn_delete_polled_interrupt);
-#endif
-
extern nasid_t master_nasid;
EXPORT_SYMBOL(master_nasid);
+
+EXPORT_SYMBOL(sn_flush_all_caches);
diff --git a/arch/ia64/sn/kernel/sv.c b/arch/ia64/sn/kernel/sv.c
index 84bedef9f6e28..0fa601f910038 100644
--- a/arch/ia64/sn/kernel/sv.c
+++ b/arch/ia64/sn/kernel/sv.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This implemenation of synchronization variables is heavily based on
* one done by Steve Lord <lord@sgi.com>