http://lia64.bkbits.net/linux-ia64-test-2.6.11
kaos@sgi.com|ChangeSet|20041213231738|36030 kaos

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/01/04 23:15:40-08:00 akpm@bix.(none) 
#   ss
# 
# arch/ia64/kernel/irq_ia64.c
#   2005/01/04 23:15:33-08:00 akpm@bix.(none) +0 -1
#   ss
# 
# kernel/sched.c
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/sched.h
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/asm-ia64/hw_irq.h
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/mm/init.c
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/kernel/irq.c
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/Kconfig
#   2005/01/04 23:03:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/13 15:17:38-08:00 kaos@sgi.com 
#   [IA64] Drop SALINFO_TIMER_DELAY from 5 minutes to 1 minute
#   
#   Experience with recoverable MCA events shows that a poll interval of 5
#   minutes for new MCA/INIT records is a bit too long.  Drop the poll
#   interval to one minute.
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/kernel/salinfo.c
#   2004/12/13 15:16:04-08:00 kaos@sgi.com +2 -2
#   Drop SALINFO_TIMER_DELAY from 5 minutes to 1 minute
# 
# ChangeSet
#   2004/12/13 15:15:28-08:00 kaos@sgi.com 
#   [IA64] Clear all corrected records as they occur
#   
#   Because MCA events are not irq safe, they cannot be logged via
#   salinfo_decode at the time that they occur.  Instead kernel salinfo.c
#   runs a timer every few minutes to check for and to clear corrected MCA
#   records.  If a second recoverable MCA occurs on the same cpu before
#   salinfo_decode has cleared the first record then OS_MCA reads the
#   record for the first MCA from SAL, which passes invalid data to the MCA
#   recovery routines.
#   
#   This patch treats all corrected records the same way, by clearing the
#   records from SAL as soon as they occur.  CMC and CPE records are
#   cleared as they are read.  Recoverable MCA records are cleared at the
#   time that we decide they can be corrected.  If salinfo_decode is not
#   running or is backlogged then we lose some logging, but that has always
#   been the case for corrected errors.
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/sal.h
#   2004/12/13 15:13:54-08:00 kaos@sgi.com +4 -0
#   Clear all corrected records as they occur
# 
# arch/ia64/kernel/salinfo.c
#   2004/12/13 15:13:50-08:00 kaos@sgi.com +11 -5
#   Clear all corrected records as they occur
# 
# arch/ia64/kernel/mca.c
#   2004/12/13 15:13:41-08:00 kaos@sgi.com +10 -1
#   Clear all corrected records as they occur
# 
# ChangeSet
#   2004/12/13 15:12:18-08:00 kaos@sgi.com 
#   [IA64] Add TIF_SIGDELAYED, delay a signal until it is safe
#   
#   Some of the work on recoverable MCA events has a requirement to send a
#   signal to a user process.  But it is not safe to send signals from
#   MCA/INIT/NMI/PMI, because the rest of the kernel is an unknown state.
#   This patch adds set_sigdelayed() which is called from the problem
#   contexts to set the delayed signal.  The delayed signal will be
#   delivered from the right context on the next transition from kernel to
#   user space.
#   
#   If TIF_SIGDELAYED is set when we run ia64_leave_kernel or
#   ia64_leave_syscall then the delayed signal is delivered and cleared.
#   All code for sigdelayed processing is on the slow paths.
#   
#   A recoverable MCA handler that wants to kill a user task just does
#   
#     set_sigdelayed(pid, signo, code, addr);
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# kernel/sched.c
#   2004/12/13 15:10:06-08:00 kaos@sgi.com +9 -0
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# include/linux/sched.h
#   2004/12/13 15:10:05-08:00 kaos@sgi.com +1 -0
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# include/asm-ia64/thread_info.h
#   2004/12/13 15:10:04-08:00 kaos@sgi.com +14 -4
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# include/asm-ia64/signal.h
#   2004/12/13 15:10:02-08:00 kaos@sgi.com +2 -0
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# arch/ia64/kernel/signal.c
#   2004/12/13 15:10:01-08:00 kaos@sgi.com +101 -0
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# arch/ia64/kernel/entry.S
#   2004/12/13 15:09:56-08:00 kaos@sgi.com +15 -0
#   Add TIF_SIGDELAYED, delay a signal until it is safe
# 
# ChangeSet
#   2004/12/10 16:29:07-08:00 tony.luck@intel.com 
#   [IA64] hardirq.h: Add declaration for ack_bad_irq().
#   
#   Cleanup a warning from my irq merge.
#   
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/hardirq.h
#   2004/12/10 16:27:45-08:00 tony.luck@intel.com +2 -0
#   Add declaration for ack_bad_irq().
# 
# ChangeSet
#   2004/12/10 13:36:35-08:00 rja@sgi.com 
#   [IA64] per cpu MCA/INIT save areas
#   
#     Linux currently has one MCA & INIT save area for saving
#     stack and other data.  This patch creates per cpu MCA 
#     save areas, so that each cpu can save its own MCA stack 
#     data.  CPU register ar.k3 is used to hold a physical 
#     address pointer to the cpuinfo structure.  The cpuinfo
#     structure has a physical address pointer to the MCA save 
#     area.  The MCA handler runs in physical mode and the 
#     physical address pointer avoids the problems associated
#     with doing the virtual to physical translation.
#   
#     The per MCA save areas replace the global areas defined
#     in arch/ia64/kernel/mca.c for MCA processor state dump, 
#     MCA stack, MCA stack frame, and MCA bspstore.
#   
#     The code to access those save areas is updated to use the
#     per cpu save areas.
#   
#     No changes are made to the MCA flow, ie all the old locks
#     are still in place.  The point of this patch is to establish
#     the per cpu save areas.  Additional usage of the save areas,
#     such as enabling concurrent INIT or MCA handling, will be
#     the subject of other patches.
#   
#   Signed-off-by: Russ Anderson <rja@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/mca_asm.h
#   2004/12/10 13:33:20-08:00 rja@sgi.com +31 -0
#   macros for syntactic sugar to access per-cpu variables
#   in physcial mode in mca/init handlers.
# 
# arch/ia64/kernel/minstate.h
#   2004/12/10 13:31:49-08:00 rja@sgi.com +5 -2
#   Modify MINSTATE_START_SAVE_MIN_PHYS to use ar.k3
# 
# arch/ia64/kernel/mca_asm.S
#   2004/12/10 13:30:21-08:00 rja@sgi.com +18 -38
#   Replace the global MCA save pointers with the
#   per CPU equivalents.  Replace ia64_mca_tlb_list
#   with cpuinfo equivalents.
# 
# arch/ia64/kernel/efi.c
#   2004/12/10 13:29:46-08:00 rja@sgi.com +65 -4
#   Add efi_get_pal_addr() to set pal_paddr and pal_base
#   in cpuinfo.  Remove ia64_mca_tlb_list[] references.
# 
# arch/ia64/kernel/mca.c
#   2004/12/10 13:28:43-08:00 rja@sgi.com +0 -7
#   Remove the global save areas: ia64_mca_proc_state_dump,
#   ia64_mca_stack, ia64_mca_stackframe, ia64_mca_bspstore,
#   ia64_init_stack and ia64_mca_tlb_info[NR_CPUS]
# 
# arch/ia64/kernel/asm-offsets.c
#   2004/12/10 13:27:55-08:00 rja@sgi.com +9 -1
#   Define assembler constants to correspond with
#   the c structure layout of cpuinfo and the MCA/INIT
#   save area.
# 
# arch/ia64/mm/discontig.c
#   2004/12/10 13:27:15-08:00 rja@sgi.com +53 -4
#   On each node, allocate MCA/INIT space for each
#   cpu that physically exists.
# 
# arch/ia64/mm/init.c
#   2004/12/10 13:26:32-08:00 rja@sgi.com +15 -12
#   Replace global array ia64_mca_tlb_list with
#   ar.k3 pointing to this cpu's cpuinfo structure.
#   Set physical address pointer to MCA save area in
#   this cpu's cpuinfo structure.
# 
# include/asm-ia64/kregs.h
#   2004/12/10 13:25:43-08:00 rja@sgi.com +1 -0
#   Define ar.k3 as used for physical address pointer
#   to this cpu's cpuinfo structure.
# 
# include/asm-ia64/mca.h
#   2004/12/10 13:25:02-08:00 rja@sgi.com +13 -11
#   Define the structure layout of the MCA/INIT save area.
#   Remove ia64_mca_tlb_info structure.  pal_paddr and
#   pal_base are moved to the cpuinfo structure.
# 
# include/asm-ia64/processor.h
#   2004/12/10 13:24:20-08:00 rja@sgi.com +4 -0
#   Add a physical address pointer to cpuinfo.
#   Add pal_paddr, pal_base, and percpu_paddr to cpuinfo.
# 
# ChangeSet
#   2004/12/10 13:14:10-08:00 steiner@sgi.com 
#   [IA64] Cachealign jiffies_64 to prevent unexpected aliasing in the caches.
#   
#   On large systems, system overhead on cpu 0 is higher than on other
#   cpus. On a completely idle 512p system, the average amount of system time 
#   on cpu 0 is 2.4%  and .15% on cpu 1-511.
#   
#   A second interesting data point is that if I run a busy-loop
#   program on cpus 1-511, the system overhead on cpu 0 drops 
#   significantly.
#   
#   I moved the timekeeper to cpu 1. The excessive system time moved
#   to cpu 1 and the system time on cpu 0 dropped to .2%.
#   
#   Further investigation showed that the problem was caused by false
#   sharing of the cacheline containing jiffies_64. On the kernel that
#   I was running, both jiffies_64 & pal_halt share the same cacheline.
#   Idle cpus are frequently accessing pal_halt. Minor kernel
#   changes (including some of the debugging code that I used to find the 
#   problem :-(  ) can cause variables to move & change the false sharing - the
#   symptoms of the problem can change or disappear.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/kernel/time.c
#   2004/12/10 13:10:05-08:00 steiner@sgi.com +1 -1
#   Cachealign jiffies_64 to prevent unexpected aliasing in the caches.
# 
# ChangeSet
#   2004/12/10 13:05:36-08:00 steiner@sgi.com 
#   [IA64-SGI] Add support for a future SGI chipset (shub2) 4of4
#   
#   Change the code that manages the LEDs so that it
#   works on both shub1 & shub2.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
# 
# include/asm-ia64/sn/shub_mmr.h
#   2004/12/10 13:04:21-08:00 steiner@sgi.com +14 -0
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/leds.h
#   2004/12/10 13:04:21-08:00 steiner@sgi.com +1 -0
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/timer_interrupt.c
#   2004/12/10 13:04:21-08:00 steiner@sgi.com +0 -1
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/setup.c
#   2004/12/10 13:04:21-08:00 steiner@sgi.com +0 -1
#   Add support for a future SGI chipset (shub2)
# 
# ChangeSet
#   2004/12/10 12:16:38-08:00 steiner@sgi.com 
#   [IA64-SGI] Add support for a future SGI chipset (shub2) 3of4
#   
#   Change the IPI & TLB flushing code so that it works on
#   both shub1 & shub2.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
# 
# include/asm-ia64/sn/rw_mmr.h
#   2004/12/10 12:15:27-08:00 steiner@sgi.com +5 -4
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/sn2_smp.c
#   2004/12/10 12:15:27-08:00 steiner@sgi.com +43 -26
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/ptc_deadlock.S
#   2004/12/10 12:15:27-08:00 steiner@sgi.com +9 -9
#   Add support for a future SGI chipset (shub2)
# 
# ChangeSet
#   2004/12/10 12:14:33-08:00 steiner@sgi.com 
#   [IA64-SGI] Add support for a future SGI chipset (shub2) 2of4
#   
#   This patch adds the addresses of shub2 MMRS to the shub_mmr
#   header file. During boot, a SAL call is made to determine the
#   type of the shub. Platform initialization sets the appropriate
#   MMR addresses for the platform.
#   
#   A new macro (is_shub1() & is_shub2()) can be used at runtime to
#   determine the type of the shub.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
# 
# include/asm-ia64/sn/sn_cpuid.h
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +2 -3
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/shub_mmr.h
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +115 -92
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/arch.h
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +2 -1
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/timer.c
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +0 -1
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/sn2_smp.c
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +14 -15
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/ptc_deadlock.S
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +3 -3
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/setup.c
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +26 -12
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/iomv.c
#   2004/12/10 12:12:43-08:00 steiner@sgi.com +5 -5
#   Add support for a future SGI chipset (shub2)
# 
# ChangeSet
#   2004/12/10 12:11:47-08:00 steiner@sgi.com 
#   [IA64-SGI] Add support for a future SGI chipset (shub2) 1of4
#   
#   This patch changes the SN macros for calulating the addresses
#   of shub MMRs. Functionally, shub1 (current chipset) and shub2
#   are very similar. The primary differences are in the addresses
#   of MMRs and in the location of the NASID (node number) in
#   a physical address. This patch adds the basic infrastructure
#   for running a single binary kernel image on either shub1 or shub2.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
# 
# include/asm-ia64/sn/sn_sal.h
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +51 -2
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/pda.h
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +10 -3
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/klconfig.h
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +1 -1
#   Add support for a future SGI chipset (shub2)
# 
# include/asm-ia64/sn/addrs.h
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +156 -231
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/sn2/timer.c
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +2 -2
#   Add support for a future SGI chipset (shub2)
# 
# arch/ia64/sn/kernel/setup.c
#   2004/12/10 12:10:33-08:00 steiner@sgi.com +10 -6
#   Add support for a future SGI chipset (shub2)
# 
# ChangeSet
#   2004/11/23 15:47:20-08:00 tony.luck@intel.com 
#   [IA64] convert to use CONFIG_GENERIC_HARDIRQS
#   
#   Convert ia64 to use generic irq handling code.
#   
#   sn2 fixes and testing by Jesse Barnes
#   
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/msi.h
#   2004/11/23 15:45:37-08:00 tony.luck@intel.com +0 -1
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
# include/asm-ia64/hw_irq.h
#   2004/11/23 15:45:36-08:00 tony.luck@intel.com +2 -2
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
# arch/ia64/sn/kernel/irq.c
#   2004/11/23 15:45:34-08:00 tony.luck@intel.com +2 -2
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
# arch/ia64/kernel/irq_ia64.c
#   2004/11/23 15:45:33-08:00 tony.luck@intel.com +2 -0
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
# arch/ia64/kernel/irq.c
#   2004/11/23 15:45:24-08:00 tony.luck@intel.com +29 -957
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
# arch/ia64/Kconfig
#   2004/11/23 15:44:58-08:00 tony.luck@intel.com +11 -0
#   convert to use CONFIG_GENERIC_HARDIRQS
# 
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/Kconfig	2005-01-05 18:28:29 -08:00
@@ -390,6 +390,17 @@
 
 source "lib/Kconfig"
 
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_HARDIRQS
+	bool
+	default y
+
+config GENERIC_IRQ_PROBE
+	bool
+	default y
+
 source "arch/ia64/hp/sim/Kconfig"
 
 source "arch/ia64/oprofile/Kconfig"
diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
--- a/arch/ia64/kernel/asm-offsets.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/asm-offsets.c	2005-01-05 18:28:29 -08:00
@@ -203,7 +203,15 @@
 #endif
 
 	BLANK();
-	DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info));
+	/* used by arch/ia64/kernel/mca_asm.S */
+	DEFINE(IA64_CPUINFO_PERCPU_PADDR, offsetof (struct cpuinfo_ia64, percpu_paddr));
+	DEFINE(IA64_CPUINFO_PA_MCA_INFO, offsetof (struct cpuinfo_ia64, ia64_pa_mca_data));
+	DEFINE(IA64_MCA_PROC_STATE_DUMP, offsetof (struct ia64_mca_cpu_s, ia64_mca_proc_state_dump));
+	DEFINE(IA64_MCA_STACK, offsetof (struct ia64_mca_cpu_s, ia64_mca_stack));
+	DEFINE(IA64_MCA_STACKFRAME, offsetof (struct ia64_mca_cpu_s, ia64_mca_stackframe));
+	DEFINE(IA64_MCA_BSPSTORE, offsetof (struct ia64_mca_cpu_s, ia64_mca_bspstore));
+	DEFINE(IA64_INIT_STACK, offsetof (struct ia64_mca_cpu_s, ia64_init_stack));
+
 	/* used by head.S */
 	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/efi.c	2005-01-05 18:28:29 -08:00
@@ -423,7 +423,6 @@
 	int pal_code_count = 0;
 	u64 mask, psr;
 	u64 vaddr;
-	int cpu;
 
 	efi_map_start = __va(ia64_boot_param->efi_memmap);
 	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -485,11 +484,73 @@
 		ia64_set_psr(psr);		/* restore psr */
 		ia64_srlz_i();
 
-		cpu = smp_processor_id();
+	}
+}
+
+/* 
+ * Put pal_base and pal_paddr in the cpuinfo structure.
+ */
+void
+efi_get_pal_addr(void)
+{
+	void *efi_map_start, *efi_map_end, *p;
+	efi_memory_desc_t *md;
+	u64 efi_desc_size;
+	int pal_code_count = 0;
+	u64 mask;
+	u64 vaddr;
+	struct cpuinfo_ia64 *cpuinfo;
+
+	efi_map_start = __va(ia64_boot_param->efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+	efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+		md = p;
+		if (md->type != EFI_PAL_CODE)
+			continue;
+
+		if (++pal_code_count > 1) {
+			printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n",
+			       md->phys_addr);
+			continue;
+		}
+		/*
+		 * The only ITLB entry in region 7 that is used is the one installed by
+		 * __start().  That entry covers a 64MB range.
+		 */
+		mask  = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
+		vaddr = PAGE_OFFSET + md->phys_addr;
+
+		/*
+		 * We must check that the PAL mapping won't overlap with the kernel
+		 * mapping.
+		 *
+		 * PAL code is guaranteed to be aligned on a power of 2 between 4k and
+		 * 256KB and that only one ITR is needed to map it. This implies that the
+		 * PAL code is always aligned on its size, i.e., the closest matching page
+		 * size supported by the TLB. Therefore PAL code is guaranteed never to
+		 * cross a 64MB unless it is bigger than 64MB (very unlikely!).  So for
+		 * now the following test is enough to determine whether or not we need a
+		 * dedicated ITR for the PAL code.
+		 */
+		if ((vaddr & mask) == (KERNEL_START & mask)) {
+			printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
+			       __FUNCTION__);
+			continue;
+		}
+
+		if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE)
+			panic("Woah!  PAL code size bigger than a granule!");
+
+		mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
 
 		/* insert this TR into our list for MCA recovery purposes */
-		ia64_mca_tlb_list[cpu].pal_base = vaddr & mask;
-		ia64_mca_tlb_list[cpu].pal_paddr = pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL));
+		cpuinfo = (struct cpuinfo_ia64 *)__va(ia64_get_kr(IA64_KR_PA_CPU_INFO));
+		cpuinfo->pal_base = vaddr & mask;
+		cpuinfo->pal_paddr = pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL));
+		printk(KERN_INFO "CPU %d: late efi pal_base 0x%lx pal_paddr 0x%lx\n",
+			smp_processor_id(), cpuinfo->pal_base, cpuinfo->pal_paddr);
 	}
 }
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/entry.S	2005-01-05 18:28:29 -08:00
@@ -1057,6 +1057,9 @@
 	 *	p6 = TRUE if work-pending-check needs to be redone
 	 */
 .work_pending:
+	tbit.nz p6,p0=r31,TIF_SIGDELAYED		// signal delayed from  MCA/INIT/NMI/PMI context?
+(p6)	br.cond.sptk.few .sigdelayed
+	;;
 	tbit.z p6,p0=r31,TIF_NEED_RESCHED		// current_thread_info()->need_resched==0?
 (p6)	br.cond.sptk.few .notify
 #ifdef CONFIG_PREEMPT
@@ -1082,6 +1085,18 @@
 .ret10:	cmp.ne p6,p0=r0,r0				// p6 <- 0
 (pLvSys)br.cond.sptk.many .work_processed_syscall	// don't re-check
 	br.cond.sptk.many .work_processed_kernel	// don't re-check
+
+// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where
+// it could not be delivered.  Deliver it now.  The signal might be for us and
+// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed
+// signal.
+
+.sigdelayed:
+	br.call.sptk.many rp=do_sigdelayed
+	cmp.eq p6,p0=r0,r0				// p6 <- 1, always re-check
+(pLvSys)br.cond.sptk.many .work_processed_syscall	// re-check
+	br.cond.sptk.many .work_processed_kernel	// re-check
+
 END(ia64_leave_kernel)
 
 ENTRY(handle_syscall_error)
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/irq.c	2005-01-05 18:28:29 -08:00
@@ -16,73 +16,31 @@
  *			architecture.
  */
 
-/*
- * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
- *
- * IRQs are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
 #include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/cpu.h>
-#include <linux/ctype.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <linux/kernel_stat.h>
-#include <linux/irq.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/kallsyms.h>
-#include <linux/notifier.h>
-#include <linux/bitops.h>
-
-#include <asm/atomic.h>
-#include <asm/cpu.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/delay.h>
-#include <asm/irq.h>
-
 
 /*
- * Linux has a controller-independent x86 interrupt architecture.
- * every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the appropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
- * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
- * (IO-APICs assumed to be messaging to Pentium local-APICs)
- *
- * the code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic.
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
  */
+void ack_bad_irq(unsigned int irq)
+{
+	printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
+}
 
 /*
- * Controller mappings for all interrupt sources:
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
  */
-irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = {
-	[0 ... NR_IRQS-1] = {
-		.status = IRQ_DISABLED,
-		.handler = &no_irq_type,
-		.lock = SPIN_LOCK_UNLOCKED
-	}
-};
+unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
+{
+	return __do_IRQ(irq, regs);
+}
 
 #ifdef CONFIG_SMP
 /*
@@ -95,7 +53,7 @@
 #ifdef CONFIG_IA64_GENERIC
 irq_desc_t * __ia64_irq_desc (unsigned int irq)
 {
-	return _irq_desc + irq;
+	return irq_desc + irq;
 }
 
 ia64_vector __ia64_irq_to_vector (unsigned int irq)
@@ -109,82 +67,24 @@
 }
 #endif
 
-static void register_irq_proc (unsigned int irq);
-
-/*
- * Special irq handlers.
- */
-
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{ return IRQ_NONE; }
-
-/*
- * Generic no controller code
- */
-
-static void enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
-{
 /*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesn't deserve
- * a generic callback i think.
+ * Interrupt statistics:
  */
-#ifdef CONFIG_X86
-	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
-#ifdef CONFIG_X86_LOCAL_APIC
-	/*
-	 * Currently unexpected vectors happen only on SMP and APIC.
-	 * We _must_ ack these because every local APIC has only N
-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
-	 * holds up an irq slot - in excessive cases (when multiple
-	 * unexpected vectors occur) that might lock up the APIC
-	 * completely.
-	 */
-	ack_APIC_irq();
-#endif
-#endif
-#ifdef CONFIG_IA64
-	printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
-#endif
-}
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none	disable_none
-#define end_none	enable_none
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	startup_none,
-	shutdown_none,
-	enable_none,
-	disable_none,
-	ack_none,
-	end_none
-};
 
 atomic_t irq_err_count;
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
-atomic_t irq_mis_count;
-#endif
-#endif
 
 /*
- * Generic, controller-independent functions:
+ * /proc/interrupts printing:
  */
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int j, i = *(loff_t *) v;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
-	irq_desc_t *idesc;
 	unsigned long flags;
 
 	if (i == 0) {
-		seq_puts(p, "           ");
+		seq_printf(p, "           ");
 		for (j=0; j<NR_CPUS; j++)
 			if (cpu_online(j))
 				seq_printf(p, "CPU%d       ",j);
@@ -192,9 +92,8 @@
 	}
 
 	if (i < NR_IRQS) {
-		idesc = irq_descp(i);
-		spin_lock_irqsave(&idesc->lock, flags);
-		action = idesc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -205,7 +104,7 @@
 			if (cpu_online(j))
 				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		seq_printf(p, " %14s", idesc->handler->typename);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -213,725 +112,25 @@
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&idesc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC)
 		seq_puts(p, "LOC: ");
 		for (j = 0; j < NR_CPUS; j++)
 			if (cpu_online(j))
-				seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+				seq_printf(p, "%10u ",
+					   irq_stat[j].apic_timer_irqs);
 		seq_putc(p, '\n');
 #endif
 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
+#if defined(CONFIG_X86_IO_APIC)
 		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
-#endif
 	}
 	return 0;
 }
 
 #ifdef CONFIG_SMP
-inline void synchronize_irq(unsigned int irq)
-{
-	while (irq_descp(irq)->status & IRQ_INPROGRESS)
-		cpu_relax();
-}
-EXPORT_SYMBOL(synchronize_irq);
-#endif
-
-/*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-int handle_IRQ_event(unsigned int irq,
-		struct pt_regs *regs, struct irqaction *action)
-{
-	int status = 1;	/* Force the "do bottom halves" bit */
-	int ret, retval = 0;
-
-	if (!(action->flags & SA_INTERRUPT))
-		local_irq_enable();
-
-	do {
-		ret = action->handler(irq, action->dev_id, regs);
-		if (ret == IRQ_HANDLED)
-			status |= action->flags;
-		retval |= ret;
-		action = action->next;
-	} while (action);
-	if (status & SA_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
-	local_irq_disable();
-	return retval;
-}
-
-static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	struct irqaction *action;
-
-	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
-		printk(KERN_ERR "irq event %d: bogus return value %x\n",
-				irq, action_ret);
-	} else {
-		printk(KERN_ERR "irq %d: nobody cared!\n", irq);
-	}
-	dump_stack();
-	printk(KERN_ERR "handlers:\n");
-	action = desc->action;
-	do {
-		printk(KERN_ERR "[<%p>]", action->handler);
-		print_symbol(" (%s)",
-			(unsigned long)action->handler);
-		printk("\n");
-		action = action->next;
-	} while (action);
-}
-
-static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	static int count = 100;
-
-	if (count) {
-		count--;
-		__report_bad_irq(irq, desc, action_ret);
-	}
-}
-
-static int noirqdebug;
-
-static int __init noirqdebug_setup(char *str)
-{
-	noirqdebug = 1;
-	printk("IRQ lockup detection disabled\n");
-	return 1;
-}
-
-__setup("noirqdebug", noirqdebug_setup);
-
-/*
- * If 99,900 of the previous 100,000 interrupts have not been handled then
- * assume that the IRQ is stuck in some manner.  Drop a diagnostic and try to
- * turn the IRQ off.
- *
- * (The other 100-of-100,000 interrupts may have been a correctly-functioning
- *  device sharing an IRQ with the failing one)
- *
- * Called under desc->lock
- */
-static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	if (action_ret != IRQ_HANDLED) {
-		desc->irqs_unhandled++;
-		if (action_ret != IRQ_NONE)
-			report_bad_irq(irq, desc, action_ret);
-	}
-
-	desc->irq_count++;
-	if (desc->irq_count < 100000)
-		return;
-
-	desc->irq_count = 0;
-	if (desc->irqs_unhandled > 99900) {
-		/*
-		 * The interrupt is stuck
-		 */
-		__report_bad_irq(irq, desc, action_ret);
-		/*
-		 * Now kill the IRQ
-		 */
-		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	desc->irqs_unhandled = 0;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
- */
-
-/**
- *	disable_irq_nosync - disable an irq without waiting
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line.  Disables and Enables are
- *	nested.
- *	Unlike disable_irq(), this function does not ensure existing
- *	instances of the IRQ handler have completed before returning.
- *
- *	This function may be called from IRQ context.
- */
-
-inline void disable_irq_nosync(unsigned int irq)
-{
-	irq_desc_t *desc = irq_descp(irq);
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	if (!desc->depth++) {
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-EXPORT_SYMBOL(disable_irq_nosync);
-
-/**
- *	disable_irq - disable an irq and wait for completion
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line.  Enables and Disables are
- *	nested.
- *	This function waits for any pending IRQ handlers for this interrupt
- *	to complete before returning. If you use this function while
- *	holding a resource the IRQ handler may need you will deadlock.
- *
- *	This function may be called - with care - from IRQ context.
- */
-
-void disable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_descp(irq);
-
-	disable_irq_nosync(irq);
-	if (desc->action)
-		synchronize_irq(irq);
-}
-EXPORT_SYMBOL(disable_irq);
-
-/**
- *	enable_irq - enable handling of an irq
- *	@irq: Interrupt to enable
- *
- *	Undoes the effect of one call to disable_irq().  If this
- *	matches the last disable, processing of interrupts on this
- *	IRQ line is re-enabled.
- *
- *	This function may be called from IRQ context.
- */
-
-void enable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_descp(irq);
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	switch (desc->depth) {
-	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
-		desc->status = status;
-		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-			desc->status = status | IRQ_REPLAY;
-			hw_resend_irq(desc->handler,irq);
-		}
-		desc->handler->enable(irq);
-		/* fall-through */
-	}
-	default:
-		desc->depth--;
-		break;
-	case 0:
-		printk(KERN_ERR "enable_irq(%u) unbalanced from %p\n",
-		       irq, (void *) __builtin_return_address(0));
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-EXPORT_SYMBOL(enable_irq);
-
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
-{
-	/*
-	 * We ack quickly, we don't want the irq controller
-	 * thinking we're snobs just because some other CPU has
-	 * disabled global interrupts (we have already done the
-	 * INT_ACK cycles, it's too late to try to pretend to the
-	 * controller that we aren't taking the interrupt).
-	 *
-	 * 0 return value means that this irq is already being
-	 * handled by some other CPU. (or is disabled)
-	 */
-	irq_desc_t *desc = irq_descp(irq);
-	struct irqaction * action;
-	irqreturn_t action_ret;
-	unsigned int status;
-	int cpu;
-
-	cpu = smp_processor_id(); /* for CONFIG_PREEMPT, this must come after irq_enter()! */
-
-	kstat_cpu(cpu).irqs[irq]++;
-
-	if (desc->status & IRQ_PER_CPU) {
-		/* no locking required for CPU-local interrupts: */
-		desc->handler->ack(irq);
-		action_ret = handle_IRQ_event(irq, regs, desc->action);
-		desc->handler->end(irq);
-	} else {
-		spin_lock(&desc->lock);
-		desc->handler->ack(irq);
-		/*
-		 * REPLAY is when Linux resends an IRQ that was dropped earlier
-		 * WAITING is used by probe to mark irqs that are being tested
-		 */
-		status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-		status |= IRQ_PENDING; /* we _want_ to handle it */
-
-		/*
-		 * If the IRQ is disabled for whatever reason, we cannot
-		 * use the action we have.
-		 */
-		action = NULL;
-		if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
-			action = desc->action;
-			status &= ~IRQ_PENDING; /* we commit to handling */
-			status |= IRQ_INPROGRESS; /* we are handling it */
-		}
-		desc->status = status;
-
-		/*
-		 * If there is no IRQ handler or it was disabled, exit early.
-		 * Since we set PENDING, if another processor is handling
-		 * a different instance of this same irq, the other processor
-		 * will take care of it.
-		 */
-		if (unlikely(!action))
-			goto out;
-
-		/*
-		 * Edge triggered interrupts need to remember
-		 * pending events.
-		 * This applies to any hw interrupts that allow a second
-		 * instance of the same irq to arrive while we are in do_IRQ
-		 * or in the handler. But the code here only handles the _second_
-		 * instance of the irq, not the third or fourth. So it is mostly
-		 * useful for irq hardware that does not mask cleanly in an
-		 * SMP environment.
-		 */
-		for (;;) {
-			spin_unlock(&desc->lock);
-			action_ret = handle_IRQ_event(irq, regs, action);
-			spin_lock(&desc->lock);
-			if (!noirqdebug)
-				note_interrupt(irq, desc, action_ret);
-			if (!(desc->status & IRQ_PENDING))
-				break;
-			desc->status &= ~IRQ_PENDING;
-		}
-		desc->status &= ~IRQ_INPROGRESS;
-	  out:
-		/*
-		 * The ->end() handler has to deal with interrupts which got
-		 * disabled while the handler was running.
-		 */
-		desc->handler->end(irq);
-		spin_unlock(&desc->lock);
-	}
-	return 1;
-}
-
-/**
- *	request_irq - allocate an interrupt line
- *	@irq: Interrupt line to allocate
- *	@handler: Function to be called when the IRQ occurs
- *	@irqflags: Interrupt type flags
- *	@devname: An ascii name for the claiming device
- *	@dev_id: A cookie passed back to the handler function
- *
- *	This call allocates interrupt resources and enables the
- *	interrupt line and IRQ handling. From the point this
- *	call is made your handler function may be invoked. Since
- *	your handler function must clear any interrupt the board 
- *	raises, you must take care both to initialise your hardware
- *	and to set up the interrupt handler in the right order.
- *
- *	Dev_id must be globally unique. Normally the address of the
- *	device data structure is used as the cookie. Since the handler
- *	receives this value it makes sense to use it.
- *
- *	If your interrupt is shared you must pass a non NULL dev_id
- *	as this is required when freeing the interrupt.
- *
- *	Flags:
- *
- *	SA_SHIRQ		Interrupt is shared
- *
- *	SA_INTERRUPT		Disable local interrupts while processing
- *
- *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
- *
- */
-
-int request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags,
-		const char * devname,
-		void *dev_id)
-{
-	int retval;
-	struct irqaction * action;
-
-#if 1
-	/*
-	 * Sanity-check: shared interrupts should REALLY pass in
-	 * a real dev-ID, otherwise we'll have trouble later trying
-	 * to figure out which interrupt is which (messes up the
-	 * interrupt freeing logic etc).
-	 */
-	if (irqflags & SA_SHIRQ) {
-		if (!dev_id)
-			printk(KERN_ERR "Bad boy: %s called us without a dev_id!\n", devname);
-	}
-#endif
-
-	if (irq >= NR_IRQS)
-		return -EINVAL;
-	if (!handler)
-		return -EINVAL;
-
-	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
-	if (!action)
-		return -ENOMEM;
-
-	action->handler = handler;
-	action->flags = irqflags;
-	cpus_clear(action->mask);
-	action->name = devname;
-	action->next = NULL;
-	action->dev_id = dev_id;
-
-	retval = setup_irq(irq, action);
-	if (retval)
-		kfree(action);
-	return retval;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-/**
- *	free_irq - free an interrupt
- *	@irq: Interrupt line to free
- *	@dev_id: Device identity to free
- *
- *	Remove an interrupt handler. The handler is removed and if the
- *	interrupt line is no longer in use by any driver it is disabled.
- *	On a shared IRQ the caller must ensure the interrupt is disabled
- *	on the card it drives before calling this function. The function
- *	does not return until any executing interrupts for this IRQ
- *	have completed.
- *
- *	This function must not be called from interrupt context.
- */
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	irq_desc_t *desc;
-	struct irqaction **p;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS)
-		return;
-
-	desc = irq_descp(irq);
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	for (;;) {
-		struct irqaction * action = *p;
-		if (action) {
-			struct irqaction **pp = p;
-			p = &action->next;
-			if (action->dev_id != dev_id)
-				continue;
-
-			/* Found it - now remove it from the list of entries */
-			*pp = action->next;
-			if (!desc->action) {
-				desc->status |= IRQ_DISABLED;
-				desc->handler->shutdown(irq);
-			}
-			spin_unlock_irqrestore(&desc->lock,flags);
-
-			/* Wait to make sure it's not being used on another CPU */
-			synchronize_irq(irq);
-			kfree(action);
-			return;
-		}
-		printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
-		spin_unlock_irqrestore(&desc->lock,flags);
-		return;
-	}
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that
- * comes in on to an unassigned handler will get stuck
- * with "IRQ_WAITING" cleared and the interrupt
- * disabled.
- */
-
-static DECLARE_MUTEX(probe_sem);
-
-/**
- *	probe_irq_on	- begin an interrupt autodetect
- *
- *	Commence probing for an interrupt. The interrupts are scanned
- *	and a mask of potential interrupt lines is returned.
- *
- */
-
-unsigned long probe_irq_on(void)
-{
-	unsigned int i;
-	irq_desc_t *desc;
-	unsigned long val;
-	unsigned long delay;
-
-	down(&probe_sem);
-	/*
-	 * something may have generated an irq long ago and we want to
-	 * flush such a longstanding irq before considering it as spurious.
-	 */
-	for (i = NR_IRQS-1; i > 0; i--)  {
-		desc = irq_descp(i);
-
-		spin_lock_irq(&desc->lock);
-		if (!desc->action)
-			desc->handler->startup(i);
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/* Wait for longstanding interrupts to trigger. */
-	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ barrier();
-
-	/*
-	 * enable any unassigned irqs
-	 * (we must startup again here because if a longstanding irq
-	 * happened in the previous stage, it may have masked itself)
-	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
-		desc = irq_descp(i);
-
-		spin_lock_irq(&desc->lock);
-		if (!desc->action) {
-			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (desc->handler->startup(i))
-				desc->status |= IRQ_PENDING;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/*
-	 * Wait for spurious interrupts to trigger
-	 */
-	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */ barrier();
-
-	/*
-	 * Now filter out any obviously spurious interrupts
-	 */
-	val = 0;
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_descp(i);
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			/* It triggered already - consider it spurious. */
-			if (!(status & IRQ_WAITING)) {
-				desc->status = status & ~IRQ_AUTODETECT;
-				desc->handler->shutdown(i);
-			} else
-				if (i < 32)
-					val |= 1 << i;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	return val;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-/**
- *	probe_irq_mask - scan a bitmap of interrupt lines
- *	@val:	mask of interrupts to consider
- *
- *	Scan the ISA bus interrupt lines and return a bitmap of
- *	active interrupts. The interrupt probe logic state is then
- *	returned to its previous value.
- *
- *	Note: we need to scan all the irq's even though we will
- *	only return ISA irq numbers - just so that we reset them
- *	all to a known state.
- */
-unsigned int probe_irq_mask(unsigned long val)
-{
-	int i;
-	unsigned int mask;
-
-	mask = 0;
-	for (i = 0; i < 16; i++) {
-		irq_desc_t *desc = irq_descp(i);
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			if (!(status & IRQ_WAITING))
-				mask |= 1 << i;
-
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->handler->shutdown(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-	up(&probe_sem);
-
-	return mask & val;
-}
-EXPORT_SYMBOL(probe_irq_mask);
-
-/**
- *	probe_irq_off	- end an interrupt autodetect
- *	@val: mask of potential interrupts (unused)
- *
- *	Scans the unused interrupt lines and returns the line which
- *	appears to have triggered the interrupt. If no interrupt was
- *	found then zero is returned. If more than one interrupt is
- *	found then minus the first candidate is returned to indicate
- *	their is doubt.
- *
- *	The interrupt probe logic state is returned to its previous
- *	value.
- *
- *	BUGS: When used in a module (which arguably shouldn't happen)
- *	nothing prevents two IRQ probe callers from overlapping. The
- *	results of this are non-optimal.
- */
-
-int probe_irq_off(unsigned long val)
-{
-	int i, irq_found, nr_irqs;
-
-	nr_irqs = 0;
-	irq_found = 0;
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_descp(i);
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			if (!(status & IRQ_WAITING)) {
-				if (!nr_irqs)
-					irq_found = i;
-				nr_irqs++;
-			}
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->handler->shutdown(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-	up(&probe_sem);
-
-	if (nr_irqs > 1)
-		irq_found = -irq_found;
-	return irq_found;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-int setup_irq(unsigned int irq, struct irqaction * new)
-{
-	int shared = 0;
-	unsigned long flags;
-	struct irqaction *old, **p;
-	irq_desc_t *desc = irq_descp(irq);
-
-	if (desc->handler == &no_irq_type)
-		return -ENOSYS;
-	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
-	 */
-	if (new->flags & SA_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
-
-	if (new->flags & SA_PERCPU_IRQ) {
-		desc->status |= IRQ_PER_CPU;
-		desc->handler = &irq_type_ia64_lsapic;
-	}
-
-	/*
-	 * The following block of code has to be executed atomically
-	 */
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&desc->lock,flags);
-			return -EBUSY;
-		}
-
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
-	}
-
-	*p = new;
-
-	if (!shared) {
-		desc->depth = 0;
-		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
-		desc->handler->startup(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock,flags);
-
-	register_irq_proc(irq);
-	return 0;
-}
-
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-
-#ifdef CONFIG_SMP
-
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
 
 static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
 
@@ -949,79 +148,6 @@
 	}
 }
 
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = sprintf(page, "%s", irq_redir[(long)data] ? "r " : "");
-
-	len += cpumask_scnprintf(page+len, count, irq_affinity[(long)data]);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
-				    unsigned long count, void *data)
-{
-	unsigned int irq = (unsigned long) data;
-	int full_count = count, err;
-	cpumask_t new_value, tmp;
-#	define R_PREFIX_LEN 16
-	char rbuf[R_PREFIX_LEN];
-	int rlen;
-	int prelen;
-	irq_desc_t *desc = irq_descp(irq);
-	unsigned long flags;
-	int redir = 0;
-
-	if (!desc->handler->set_affinity)
-		return -EIO;
-
-	/*
-	 * If string being written starts with a prefix of 'r' or 'R'
-	 * and some limited number of spaces, set IA64_IRQ_REDIRECTED.
-	 * If more than (R_PREFIX_LEN - 2) spaces are passed, they won't
-	 * all be trimmed as part of prelen, the untrimmed spaces will
-	 * cause the hex parsing to fail, and this write() syscall will
-	 * fail with EINVAL.
-	 */
-
-	if (!count)
-		return -EINVAL;
-	rlen = min(sizeof(rbuf)-1, count);
-	if (copy_from_user(rbuf, buffer, rlen))
-		return -EFAULT;
-	rbuf[rlen] = 0;
-	prelen = 0;
-	if (tolower(*rbuf) == 'r') {
-		prelen = strspn(rbuf, "Rr ");
-		redir++;
-	}
-
-	err = cpumask_parse(buffer+prelen, count-prelen, new_value);
-	if (err)
-		return err;
-
-	/*
-	 * Do not allow disabling IRQs completely - it's a too easy
-	 * way to make the system unusable accidentally :-) At least
-	 * one online CPU still has to be targeted.
-	 */
-	cpus_and(tmp, new_value, cpu_online_map);
-	if (cpus_empty(tmp))
-		return -EINVAL;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	pending_irq_cpumask[irq] = new_value;
-	if (redir)
-		set_bit(irq, pending_irq_redir);
-	else
-		clear_bit(irq, pending_irq_redir);
-	spin_unlock_irqrestore(&desc->lock, flags);
-
-	return full_count;
-}
 
 void move_irq(int irq)
 {
@@ -1138,57 +264,3 @@
 	local_irq_disable();
 }
 #endif
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
-	char name [MAX_NAMELEN];
-
-	if (!root_irq_dir || (irq_descp(irq)->handler == &no_irq_type) || irq_dir[irq])
-		return;
-
-	memset(name, 0, MAX_NAMELEN);
-	sprintf(name, "%d", irq);
-
-	/* create /proc/irq/1234 */
-	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-
-#ifdef CONFIG_SMP
-	{
-		struct proc_dir_entry *entry;
-
-		/* create /proc/irq/1234/smp_affinity */
-		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
-		if (entry) {
-			entry->nlink = 1;
-			entry->data = (void *)(long)irq;
-			entry->read_proc = irq_affinity_read_proc;
-			entry->write_proc = irq_affinity_write_proc;
-		}
-
-		smp_affinity_entry[irq] = entry;
-	}
-#endif
-}
-
-void init_irq_proc (void)
-{
-	int i;
-
-	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", NULL);
-
-	/* create /proc/irq/prof_cpu_mask */
-	create_prof_cpu_mask(root_irq_dir);
-
-	/*
-	 * Create entries for all existing IRQs.
-	 */
-	for (i = 0; i < NR_IRQS; i++) {
-		if (irq_descp(i)->handler == &no_irq_type)
-			continue;
-		register_irq_proc(i);
-	}
-}
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/mca.c	2005-01-05 18:28:29 -08:00
@@ -85,11 +85,6 @@
 /* Used by mca_asm.S */
 ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
 ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
-u64				ia64_mca_proc_state_dump[512];
-u64				ia64_mca_stack[1024] __attribute__((aligned(16)));
-u64				ia64_mca_stackframe[32];
-u64				ia64_mca_bspstore[1024];
-u64				ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16)));
 u64				ia64_mca_serialize;
 
 /* In mca_asm.S */
@@ -98,8 +93,6 @@
 
 static ia64_mc_info_t		ia64_mc_info;
 
-struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
-
 #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
 #define MIN_CPE_POLL_INTERVAL (2*60*HZ)  /* 2 minutes */
 #define CMC_POLL_INTERVAL     (1*60*HZ)  /* 1 minute */
@@ -240,6 +233,7 @@
 ia64_mca_log_sal_error_record(int sal_info_type)
 {
 	u8 *buffer;
+	sal_log_record_header_t *rh;
 	u64 size;
 	int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;
 #ifdef IA64_MCA_DEBUG_INFO
@@ -258,7 +252,8 @@
 			sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN");
 
 	/* Clear logs from corrected errors in case there's no user-level logger */
-	if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC)
+	rh = (sal_log_record_header_t *)buffer;
+	if (rh->severity == sal_log_severity_corrected)
 		ia64_sal_clear_state_info(sal_info_type);
 }
 
@@ -887,6 +882,13 @@
 			&ia64_sal_to_os_handoff_state,
 			&ia64_os_to_sal_handoff_state)); 
 
+return_to_sal:
+
+	if (recover) {
+		sal_log_record_header_t *rh = IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA);
+		rh->severity = sal_log_severity_corrected;
+		ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
+	}
 	/*
 	 *  Wakeup all the processors which are spinning in the rendezvous
 	 *  loop.
diff -Nru a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
--- a/arch/ia64/kernel/mca_asm.S	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/mca_asm.S	2005-01-05 18:28:29 -08:00
@@ -13,6 +13,9 @@
 //		   2. Restore current thread pointer to kr6
 //		   3. Move stack ptr 16 bytes to conform to C calling convention
 //
+// 04/11/12 Russ Anderson <rja@sgi.com>
+//		   Added per cpu MCA/INIT stack save areas.
+//
 #include <linux/config.h>
 #include <linux/threads.h>
 
@@ -102,11 +105,6 @@
 	.global ia64_os_mca_dispatch_end
 	.global ia64_sal_to_os_handoff_state
 	.global	ia64_os_to_sal_handoff_state
-	.global	ia64_mca_proc_state_dump
-	.global	ia64_mca_stack
-	.global	ia64_mca_stackframe
-	.global	ia64_mca_bspstore
-	.global ia64_init_stack
 
 	.text
 	.align 16
@@ -146,23 +144,12 @@
 	// The following code purges TC and TR entries. Then reload all TC entries.
 	// Purge percpu data TC entries.
 begin_tlb_purge_and_reload:
-	mov r16=cr.lid
-	LOAD_PHYSICAL(p0,r17,ia64_mca_tlb_list) // Physical address of ia64_mca_tlb_list
-	mov r19=0
-	mov r20=NR_CPUS
-	;;
-1:	cmp.eq p6,p7=r19,r20
-(p6)	br.spnt.few err
-	ld8 r18=[r17],IA64_MCA_TLB_INFO_SIZE
-	;;
-	add r19=1,r19
-	cmp.eq p6,p7=r18,r16
-(p7)	br.sptk.few 1b
+	GET_PERCPU_PADDR(r2)	// paddr of percpu_paddr in cpuinfo struct
 	;;
-	adds r17=-IA64_MCA_TLB_INFO_SIZE,r17
+	mov	r17=r2
+	mov 	r23=r2		// save current ia64_mca_percpu_info addr pointer.
 	;;
-	mov r23=r17		// save current ia64_mca_percpu_info addr pointer.
-	adds r17=16,r17
+	adds r17=8,r17
 	;;
 	ld8 r18=[r17],8		// r18=ptce_base
   	;;
@@ -215,7 +202,7 @@
 	srlz.d
 	;;
 	// 3. Purge ITR for PAL code.
-	adds r17=48,r23
+	adds r17=40,r23
 	;;
 	ld8 r16=[r17]
 	mov r18=IA64_GRANULE_SHIFT<<2
@@ -260,7 +247,7 @@
 	srlz.d
 	;;
 	// 2. Reload DTR register for PERCPU data.
-	adds r17=8,r23
+	mov r17=r23
 	movl r16=PERCPU_ADDR		// vaddr
 	movl r18=PERCPU_PAGE_SHIFT<<2
 	;;
@@ -318,17 +305,14 @@
 done_tlb_purge_and_reload:
 
 	// Setup new stack frame for OS_MCA handling
-	movl	r2=ia64_mca_bspstore;;	// local bspstore area location in r2
-	DATA_VA_TO_PA(r2);;
-	movl	r3=ia64_mca_stackframe;; // save stack frame to memory in r3
-	DATA_VA_TO_PA(r3);;
+	GET_MCA_BSPSTORE(r2)		// paddr of bspstore save area
+	GET_MCA_STACKFRAME(r3);;	// paddr of stack frame save area
 	rse_switch_context(r6,r3,r2);;	// RSC management in this new context
-	movl	r12=ia64_mca_stack
-	mov	r2=8*1024;;		// stack size must be same as C array
-	add	r12=r2,r12;;		// stack base @ bottom of array
-	adds	r12=-16,r12;;		// allow 16 bytes of scratch
+	GET_MCA_STACK(r2);;		// paddr of stack save area
+					// stack size must be same as C array
+	addl	r2=8*1024-16,r2;;	// stack base @ bottom of array
+	mov	r12=r2			// allow 16 bytes of scratch
 					// (C calling convention)
-	DATA_VA_TO_PA(r12);;
 
         // Enter virtual mode from physical mode
 	VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
@@ -344,9 +328,7 @@
 ia64_os_mca_virtual_end:
 
 	// restore the original stack frame here
-	movl    r2=ia64_mca_stackframe	// restore stack frame from memory at r2
-	;;
-	DATA_VA_TO_PA(r2)
+	GET_MCA_STACKFRAME(r2);;	// phys addr of MCA save area
 	movl    r4=IA64_PSR_MC
 	;;
 	rse_return_context(r4,r3,r2)	// switch from interrupt context for RSE
@@ -387,7 +369,7 @@
 ia64_os_mca_proc_state_dump:
 // Save bank 1 GRs 16-31 which will be used by c-language code when we switch
 //  to virtual addressing mode.
-	LOAD_PHYSICAL(p0,r2,ia64_mca_proc_state_dump)// convert OS state dump area to physical address
+	GET_MCA_DUMP_PADDR(r2);;  // phys addr of MCA save area
 
 // save ar.NaT
 	mov		r5=ar.unat                  // ar.unat
@@ -618,9 +600,7 @@
 ia64_os_mca_proc_state_restore:
 
 // Restore bank1 GR16-31
-	movl		r2=ia64_mca_proc_state_dump	// Convert virtual address
-	;;						// of OS state dump area
-	DATA_VA_TO_PA(r2)				// to physical address
+	GET_MCA_DUMP_PADDR(r2);;		// phys addr of proc state dump area
 
 restore_GRs:                                    // restore bank-1 GRs 16-31
 	bsw.1;;
diff -Nru a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
--- a/arch/ia64/kernel/minstate.h	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/minstate.h	2005-01-05 18:28:29 -08:00
@@ -37,12 +37,15 @@
  * go virtual and don't want to destroy the iip or ipsr.
  */
 #define MINSTATE_START_SAVE_MIN_PHYS								\
-(pKStk) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE;				\
+(pKStk) mov r3=ar.k3;;										\
+(pKStk) addl r3=IA64_CPUINFO_PA_MCA_INFO,r3;;							\
+(pKStk) ld8 r3 = [r3];;										\
+(pKStk) addl r3=IA64_INIT_STACK,r3;;								\
+(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3;						\
 (pUStk)	mov ar.rsc=0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
 (pUStk)	addl r22=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	\
 	;;											\
 (pUStk)	mov r24=ar.rnat;									\
-(pKStk) tpa r1=sp;				/* compute physical addr of sp	*/		\
 (pUStk)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
 (pUStk)	mov r23=ar.bspstore;				/* save ar.bspstore */			\
 (pUStk)	dep r22=-1,r22,61,3;			/* compute kernel virtual addr of RBS */	\
diff -Nru a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
--- a/arch/ia64/kernel/salinfo.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/salinfo.c	2005-01-05 18:28:29 -08:00
@@ -19,6 +19,9 @@
  *
  * Jan 28 2004	kaos@sgi.com
  *   Periodically check for outstanding MCA or INIT records.
+ *
+ * Dec  5 2004	kaos@sgi.com
+ *   Standardize which records are cleared automatically.
  */
 
 #include <linux/types.h>
@@ -230,8 +233,8 @@
 	}
 }
 
-/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */
-#define SALINFO_TIMER_DELAY (5*60*HZ)
+/* Check for outstanding MCA/INIT records every minute (arbitrary) */
+#define SALINFO_TIMER_DELAY (60*HZ)
 static struct timer_list salinfo_timer;
 
 static void
@@ -382,8 +385,11 @@
 salinfo_log_read_cpu(void *context)
 {
 	struct salinfo_data *data = context;
+	sal_log_record_header_t *rh;
 	data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);
-	if (data->type == SAL_INFO_TYPE_CPE || data->type == SAL_INFO_TYPE_CMC)
+	rh = (sal_log_record_header_t *)(data->log_buffer);
+	/* Clear corrected errors as they are read from SAL */
+	if (rh->severity == sal_log_severity_corrected)
 		ia64_sal_clear_state_info(data->type);
 }
 
@@ -457,6 +463,7 @@
 static int
 salinfo_log_clear(struct salinfo_data *data, int cpu)
 {
+	sal_log_record_header_t *rh;
 	data->state = STATE_NO_DATA;
 	if (!test_bit(cpu, &data->cpu_event))
 		return 0;
@@ -469,10 +476,9 @@
 		data->saved_num = 0;
 		spin_unlock_irqrestore(&data_saved_lock, flags);
 	}
-	/* ia64_mca_log_sal_error_record or salinfo_log_read_cpu already cleared
-	 * CPE and CMC errors
-	 */
-	if (data->type != SAL_INFO_TYPE_CPE && data->type != SAL_INFO_TYPE_CMC)
+	rh = (sal_log_record_header_t *)(data->log_buffer);
+	/* Corrected errors have already been cleared from SAL */
+	if (rh->severity != sal_log_severity_corrected)
 		call_on_cpu(cpu, salinfo_log_clear_cpu, data);
 	/* clearing a record may make a new record visible */
 	salinfo_log_new_read(cpu, data);
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/signal.c	2005-01-05 18:28:29 -08:00
@@ -589,3 +589,104 @@
 	}
 	return 0;
 }
+
+/* Set a delayed signal that was detected in MCA/INIT/NMI/PMI context where it
+ * could not be delivered.  It is important that the target process is not
+ * allowed to do any more work in user space.  Possible cases for the target
+ * process:
+ *
+ * - It is sleeping and will wake up soon.  Store the data in the current task,
+ *   the signal will be sent when the current task returns from the next
+ *   interrupt.
+ *
+ * - It is running in user context.  Store the data in the current task, the
+ *   signal will be sent when the current task returns from the next interrupt.
+ *
+ * - It is running in kernel context on this or another cpu and will return to
+ *   user context.  Store the data in the target task, the signal will be sent
+ *   to itself when the target task returns to user space.
+ *
+ * - It is running in kernel context on this cpu and will sleep before
+ *   returning to user context.  Because this is also the current task, the
+ *   signal will not get delivered and the task could sleep indefinitely.
+ *   Store the data in the idle task for this cpu, the signal will be sent
+ *   after the idle task processes its next interrupt.
+ *
+ * To cover all cases, store the data in the target task, the current task and
+ * the idle task on this cpu.  Whatever happens, the signal will be delivered
+ * to the target task before it can do any useful user space work.  Multiple
+ * deliveries have no unwanted side effects.
+ *
+ * Note: This code is executed in MCA/INIT/NMI/PMI context, with interrupts
+ * disabled.  It must not take any locks nor use kernel structures or services
+ * that require locks.
+ */
+
+/* To ensure that we get the right pid, check its start time.  To avoid extra
+ * include files in thread_info.h, convert the task start_time to unsigned long,
+ * giving us a cycle time of > 580 years.
+ */
+static inline unsigned long
+start_time_ul(const struct task_struct *t)
+{
+	return t->start_time.tv_sec * NSEC_PER_SEC + t->start_time.tv_nsec;
+}
+
+void
+set_sigdelayed(pid_t pid, int signo, int code, void __user *addr)
+{
+	struct task_struct *t;
+	unsigned long start_time =  0;
+	int i;
+
+	for (i = 1; i <= 3; ++i) {
+		switch (i) {
+		case 1:
+			t = find_task_by_pid(pid);
+			if (t)
+				start_time = start_time_ul(t);
+			break;
+		case 2:
+			t = current;
+			break;
+		default:
+			t = idle_task(smp_processor_id());
+			break;
+		}
+
+		if (!t)
+			return;
+		t->thread_info->sigdelayed.signo = signo;
+		t->thread_info->sigdelayed.code = code;
+		t->thread_info->sigdelayed.addr = addr;
+		t->thread_info->sigdelayed.start_time = start_time;
+		t->thread_info->sigdelayed.pid = pid;
+		wmb();
+		set_tsk_thread_flag(t, TIF_SIGDELAYED);
+	}
+}
+
+/* Called from entry.S when it detects TIF_SIGDELAYED, a delayed signal that
+ * was detected in MCA/INIT/NMI/PMI context where it could not be delivered.
+ */
+
+void
+do_sigdelayed(void)
+{
+	struct siginfo siginfo;
+	pid_t pid;
+	struct task_struct *t;
+
+	clear_thread_flag(TIF_SIGDELAYED);
+	memset(&siginfo, 0, sizeof(siginfo));
+	siginfo.si_signo = current_thread_info()->sigdelayed.signo;
+	siginfo.si_code = current_thread_info()->sigdelayed.code;
+	siginfo.si_addr = current_thread_info()->sigdelayed.addr;
+	pid = current_thread_info()->sigdelayed.pid;
+	t = find_task_by_pid(pid);
+	if (!t)
+		return;
+	if (current_thread_info()->sigdelayed.start_time != start_time_ul(t))
+		return;
+	force_sig_info(siginfo.si_signo, &siginfo, t);
+}
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/kernel/time.c	2005-01-05 18:28:29 -08:00
@@ -32,7 +32,7 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
+u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
 
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/mm/discontig.c	2005-01-05 18:28:29 -08:00
@@ -4,6 +4,10 @@
  * Copyright (c) 2001 Tony Luck <tony.luck@intel.com>
  * Copyright (c) 2002 NEC Corp.
  * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
+ * Copyright (c) 2004 Silicon Graphics, Inc
+ *	Russ Anderson <rja@sgi.com>
+ *	Jesse Barnes <jbarnes@sgi.com>
+ *	Jack Steiner <steiner@sgi.com>
  */
 
 /*
@@ -22,6 +26,7 @@
 #include <asm/meminit.h>
 #include <asm/numa.h>
 #include <asm/sections.h>
+#include <asm/mca.h>
 
 /*
  * Track per-node information needed to setup the boot memory allocator, the
@@ -220,12 +225,34 @@
 }
 
 /**
+ * early_nr_phys_cpus_node - return number of physical cpus on a given node
+ * @node: node to check
+ *
+ * Count the number of physical cpus on @node.  These are cpus that actually
+ * exist.  We can't use nr_cpus_node() yet because
+ * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
+ * called yet.
+ */
+static int early_nr_phys_cpus_node(int node)
+{
+	int cpu, n = 0;
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		if (node == node_cpuid[cpu].nid)
+			if ((cpu == 0) || node_cpuid[cpu].phys_id)
+				n++;
+
+	return n;
+}
+
+
+/**
  * early_nr_cpus_node - return number of cpus on a given node
  * @node: node to check
  *
  * Count the number of cpus on @node.  We can't use nr_cpus_node() yet because
  * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
- * called yet.
+ * called yet.  Note that node 0 will also count all non-existent cpus.
  */
 static int early_nr_cpus_node(int node)
 {
@@ -252,12 +279,15 @@
  *   |                        |
  *   |~~~~~~~~~~~~~~~~~~~~~~~~| <-- NODEDATA_ALIGN(start, node) for the first
  *   |    PERCPU_PAGE_SIZE *  |     start and length big enough
- *   |        NR_CPUS         |
+ *   |    cpus_on_this_node   | Node 0 will also have entries for all non-existent cpus.
  *   |------------------------|
  *   |   local pg_data_t *    |
  *   |------------------------|
  *   |  local ia64_node_data  |
  *   |------------------------|
+ *   |    MCA/INIT data *     |
+ *   |    cpus_on_this_node   |
+ *   |------------------------|
  *   |          ???           |
  *   |________________________|
  *
@@ -269,9 +299,9 @@
 static int __init find_pernode_space(unsigned long start, unsigned long len,
 				     int node)
 {
-	unsigned long epfn, cpu, cpus;
+	unsigned long epfn, cpu, cpus, phys_cpus;
 	unsigned long pernodesize = 0, pernode, pages, mapsize;
-	void *cpu_data;
+	void *cpu_data, *mca_data_phys;
 	struct bootmem_data *bdp = &mem_data[node].bootmem_data;
 
 	epfn = (start + len) >> PAGE_SHIFT;
@@ -295,9 +325,11 @@
 	 * for good alignment and alias prevention.
 	 */
 	cpus = early_nr_cpus_node(node);
+	phys_cpus = early_nr_phys_cpus_node(node);
 	pernodesize += PERCPU_PAGE_SIZE * cpus;
 	pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
 	pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+	pernodesize += L1_CACHE_ALIGN(sizeof(ia64_mca_cpu_t)) * phys_cpus;
 	pernodesize = PAGE_ALIGN(pernodesize);
 	pernode = NODEDATA_ALIGN(start, node);
 
@@ -316,6 +348,9 @@
 		mem_data[node].node_data = __va(pernode);
 		pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
 
+		mca_data_phys = (void *)pernode;
+		pernode += L1_CACHE_ALIGN(sizeof(ia64_mca_cpu_t)) * phys_cpus;
+
 		mem_data[node].pgdat->bdata = bdp;
 		pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
@@ -328,6 +363,20 @@
 			if (node == node_cpuid[cpu].nid) {
 				memcpy(__va(cpu_data), __phys_per_cpu_start,
 				       __per_cpu_end - __per_cpu_start);
+				if ((cpu == 0) || (node_cpuid[cpu].phys_id > 0)) {
+					/* 
+					 * The memory for the cpuinfo structure is allocated
+					 * here, but the data in the structure is initialized
+					 * later.  Save the physical address of the MCA save
+					 * area in IA64_KR_PA_CPU_INFO.  When the cpuinfo struct 
+					 * is initialized, the value in IA64_KR_PA_CPU_INFO
+					 * will be put in the cpuinfo structure and 
+					 * IA64_KR_PA_CPU_INFO will be set to the physical
+					 * addresss of the cpuinfo structure.
+					 */
+					ia64_set_kr(IA64_KR_PA_CPU_INFO, __pa(mca_data_phys));
+					mca_data_phys += L1_CACHE_ALIGN(sizeof(ia64_mca_cpu_t));
+				}
 				__per_cpu_offset[cpu] = (char*)__va(cpu_data) -
 					__per_cpu_start;
 				cpu_data += PERCPU_PAGE_SIZE;
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/mm/init.c	2005-01-05 18:28:29 -08:00
@@ -40,6 +40,7 @@
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 extern void ia64_tlb_init (void);
+extern void efi_get_pal_addr (void);
 
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
 
@@ -296,7 +297,7 @@
 {
 	unsigned long psr, pta, impl_va_bits;
 	extern void __devinit tlb_init (void);
-	int cpu;
+	struct cpuinfo_ia64 *cpuinfo;
 
 #ifdef CONFIG_DISABLE_VHPT
 #	define VHPT_ENABLE_BIT	0
@@ -362,19 +363,21 @@
 	ia64_srlz_d();
 #endif
 
-	cpu = smp_processor_id();
+	/*
+	 * The MCA info structure was allocated earlier and a physical address pointer
+	 * saved in k3.  Move that pointer into the cpuinfo structure and save
+	 * the physical address of the cpuinfo structure in k3.
+	 */
+	cpuinfo = (struct cpuinfo_ia64 *)my_cpu_data;
+	cpuinfo->ia64_pa_mca_data = (__u64 *)ia64_get_kr(IA64_KR_PA_CPU_INFO);
 
-	/* mca handler uses cr.lid as key to pick the right entry */
-	ia64_mca_tlb_list[cpu].cr_lid = ia64_getreg(_IA64_REG_CR_LID);
+	cpuinfo->percpu_paddr = pte_val(mk_pte_phys(__pa(my_cpu_data), PAGE_KERNEL));
+	ia64_set_kr(IA64_KR_PA_CPU_INFO, __pa(my_cpu_data));
 
-	/* insert this percpu data information into our list for MCA recovery purposes */
-	ia64_mca_tlb_list[cpu].percpu_paddr = pte_val(mk_pte_phys(__pa(my_cpu_data), PAGE_KERNEL));
-	/* Also save per-cpu tlb flush recipe for use in physical mode mca handler */
-	ia64_mca_tlb_list[cpu].ptce_base = local_cpu_data->ptce_base;
-	ia64_mca_tlb_list[cpu].ptce_count[0] = local_cpu_data->ptce_count[0];
-	ia64_mca_tlb_list[cpu].ptce_count[1] = local_cpu_data->ptce_count[1];
-	ia64_mca_tlb_list[cpu].ptce_stride[0] = local_cpu_data->ptce_stride[0];
-	ia64_mca_tlb_list[cpu].ptce_stride[1] = local_cpu_data->ptce_stride[1];
+	/*
+	 * Set pal_base and pal_paddr in cpuinfo structure.
+	 */
+	efi_get_pal_addr();
 }
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
--- a/arch/ia64/sn/kernel/iomv.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/iomv.c	2005-01-05 18:28:29 -08:00
@@ -42,8 +42,7 @@
 		 */
 		if ((port >= 0x1f0 && port <= 0x1f7) ||
 		    port == 0x3f6 || port == 0x3f7) {
-			io_base = (0xc000000fcc000000UL |
-				   ((unsigned long)get_nasid() << 38));
+			io_base = GLOBAL_MMR_ADDR(get_nasid(), 0xfcc000000UL);
 			addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
 		} else {
 			addr = __ia64_get_io_port_base() | ((port >> 2) << 2);
@@ -66,9 +65,10 @@
  */
 void __sn_mmiowb(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)
+	volatile unsigned long *adr = pda->pio_write_status_addr;
+	unsigned long val = pda->pio_write_status_val;
+
+	while ((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != val)
 		cpu_relax();
 }
 
diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- a/arch/ia64/sn/kernel/irq.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/irq.c	2005-01-05 18:28:29 -08:00
@@ -204,7 +204,7 @@
 
 struct irq_desc *sn_irq_desc(unsigned int irq)
 {
-	return (_irq_desc + irq);
+	return (irq_desc + irq);
 }
 
 u8 sn_irq_to_vector(unsigned int irq)
@@ -220,7 +220,7 @@
 void sn_irq_init(void)
 {
 	int i;
-	irq_desc_t *base_desc = _irq_desc;
+	irq_desc_t *base_desc = irq_desc;
 
 	for (i = 0; i < NR_IRQS; i++) {
 		if (base_desc[i].handler == &no_irq_type) {
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/setup.c	2005-01-05 18:28:29 -08:00
@@ -40,7 +40,6 @@
 #include <asm/sn/nodepda.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/simulator.h>
-#include "shub.h"
 #include <asm/sn/leds.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/shub_mmr.h>
@@ -215,8 +214,10 @@
 	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;
+	if (is_shub2())
+		return 0;
+	id = REMOTE_HUB_L(nasid, SH1_SHUB_ID);
+	rev = (id & SH1_SHUB_ID_REVISION_MASK) >> SH1_SHUB_ID_REVISION_SHFT;
 	return rev <= 2;
 }
 
@@ -224,9 +225,13 @@
 {
 	int cnode;
 
-	for (cnode = 0; cnode < numnodes; cnode++)
-		if (is_shub_1_1(cnodeid_to_nasid(cnode)))
-			shub_1_1_found = 1;
+	if (is_shub2()) {
+		/* none yet */
+	} else {
+		for (cnode = 0; cnode < numnodes; cnode++)
+			if (is_shub_1_1(cnodeid_to_nasid(cnode)))
+				shub_1_1_found = 1;
+	}
 }
 
 /**
@@ -340,7 +345,7 @@
  *
  * One time setup for Node Data Area.  Called by sn_setup().
  */
-void __init sn_init_pdas(char **cmdline_p)
+static void __init sn_init_pdas(char **cmdline_p)
 {
 	cnodeid_t cnode;
 
@@ -416,8 +421,17 @@
 	int slice;
 	int cnode;
 	int i;
+	u64 shubtype, nasid_bitmask, nasid_shift;
 	static int wars_have_been_checked;
 
+	memset(pda, 0, sizeof(pda));
+	if (ia64_sn_get_hub_info(0, &shubtype, &nasid_bitmask, &nasid_shift))
+		BUG();
+	pda->shub2 = (u8)shubtype;
+	pda->nasid_bitmask = (u16)nasid_bitmask;
+	pda->nasid_shift = (u8)nasid_shift;
+	pda->as_shift = pda->nasid_shift - 2;
+
 	/*
 	 * The boot cpu makes this call again after platform initialization is
 	 * complete.
@@ -441,7 +455,6 @@
 
 	cnode = nasid_to_cnodeid(nasid);
 
-	memset(pda, 0, sizeof(pda));
 	pda->p_nodepda = nodepdaindr[cnode];
 	pda->led_address =
 	    (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
@@ -469,25 +482,29 @@
 	pda->shub_1_1_found = shub_1_1_found;
 
 	/*
-	 * We must use different memory allocators for first cpu (bootmem 
-	 * allocator) than for the other cpus (regular allocator).
+	 * Set up addresses of PIO/MEM write status registers.
 	 */
-	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 *)
-	    LOCAL_MMR_ADDR((slice <
-			    2 ? SH_MEMORY_WRITE_STATUS_0 :
-			    SH_MEMORY_WRITE_STATUS_1));
+	{
+		u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
+		u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_1, 
+			SH2_PIO_WRITE_STATUS_2, SH2_PIO_WRITE_STATUS_3};
+		u64 *pio;
+		pio = is_shub1() ? pio1 : pio2;
+		pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
+		pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
+	}
 
-	if (local_node_data->active_cpu_count++ == 0) {
+	/*
+	 * WAR addresses for SHUB 1.x.
+	 */
+	if (local_node_data->active_cpu_count++ == 0 && is_shub1()) {
 		int buddy_nasid;
 		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);
+							      SH1_PI_CAM_CONTROL);
 	}
 }
 
diff -Nru a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
--- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S	2005-01-05 18:28:29 -08:00
@@ -8,34 +8,33 @@
 
 #include <asm/sn/shub_mmr.h>
 
-#define ZEROVAL		0x3f		// "zero" value for outstanding PIO requests
-#define DEADLOCKBIT	SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT
-#define WRITECOUNT	SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT
-#define ALIAS_OFFSET	(SH_PIO_WRITE_STATUS_0_ALIAS-SH_PIO_WRITE_STATUS_0)
+#define DEADLOCKBIT	SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT
+#define WRITECOUNTMASK	SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
+#define ALIAS_OFFSET	(SH1_PIO_WRITE_STATUS_0_ALIAS-SH1_PIO_WRITE_STATUS_0)
 
 
 	.global	sn2_ptc_deadlock_recovery_core
 	.proc  	sn2_ptc_deadlock_recovery_core
 
 sn2_ptc_deadlock_recovery_core:
-	.regstk 5,0,0,0
+	.regstk 6,0,0,0
 
 	ptc0  	 = in0
 	data0 	 = in1
 	ptc1  	 = in2
 	data1 	 = in3
 	piowc 	 = in4
+	zeroval  = in5
 	piowcphy = r30
 	psrsave  = r2
-	zeroval  = r3
 	scr1	 = r16
 	scr2	 = r17
+	mask	 = r18
 
 
 	extr.u	piowcphy=piowc,0,61;;	// Convert piowc to uncached physical address
 	dep	piowcphy=-1,piowcphy,63,1
-
-	mov	zeroval=ZEROVAL		// "zero" value for PIO write count
+	movl	mask=WRITECOUNTMASK
 
 1:
 	add	scr2=ALIAS_OFFSET,piowc	// Address of WRITE_STATUS alias register 
@@ -43,7 +42,7 @@
 	st8.rel	[scr2]=scr1;;
 
 5:	ld8.acq	scr1=[piowc];;		// Wait for PIOs to complete.
-	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	and	scr2=scr1,mask;;	// mask of writecount bits
 	cmp.ne	p6,p0=zeroval,scr2
 (p6)	br.cond.sptk 5b
 	
@@ -57,16 +56,17 @@
 	st8.rel [ptc0]=data0		// Write PTC0 & wait for completion.
 
 5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
-	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	and	scr2=scr1,mask;;	// mask of writecount bits
 	cmp.ne	p6,p0=zeroval,scr2
 (p6)	br.cond.sptk 5b;;
 
 	tbit.nz	p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK
+(p7)	cmp.ne p7,p0=r0,ptc1;;		// Test for non-null ptc1
 	
 (p7)	st8.rel [ptc1]=data1;;		// Now write PTC1.
 
 5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
-	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	and	scr2=scr1,mask;;	// mask of writecount bits
 	cmp.ne	p6,p0=zeroval,scr2
 (p6)	br.cond.sptk 5b
 	
diff -Nru a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c	2005-01-05 18:28:29 -08:00
@@ -38,7 +38,8 @@
 #include <asm/sn/nodepda.h>
 #include <asm/sn/rw_mmr.h>
 
-void sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1);
+void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0, 
+	volatile unsigned long *, unsigned long data1);
 
 static spinlock_t sn2_global_ptc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
 
@@ -46,15 +47,14 @@
 
 static inline unsigned long wait_piowc(void)
 {
-	volatile unsigned long *piows;
+	volatile unsigned long *piows, zeroval;
 	unsigned long ws;
 
 	piows = pda->pio_write_status_addr;
+	zeroval = pda->pio_write_status_val;
 	do {
-		ia64_mfa();
-	} while (((ws =
-		   *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) !=
-		 SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK);
+		cpu_relax();
+	} while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval);
 	return ws;
 }
 
@@ -88,9 +88,9 @@
 sn2_global_tlb_purge(unsigned long start, unsigned long end,
 		     unsigned long nbits)
 {
-	int i, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
+	int i, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
 	volatile unsigned long *ptc0, *ptc1;
-	unsigned long flags = 0, data0, data1;
+	unsigned long flags = 0, data0 = 0, data1 = 0;
 	struct mm_struct *mm = current->active_mm;
 	short nasids[NR_NODES], nix;
 	DECLARE_BITMAP(nodes_flushed, NR_NODES);
@@ -129,28 +129,42 @@
 	     cnode = find_next_bit(&nodes_flushed, NR_NODES, ++cnode))
 		nasids[nix++] = cnodeid_to_nasid(cnode);
 
-	data0 = (1UL << SH_PTC_0_A_SHFT) |
-	    (nbits << SH_PTC_0_PS_SHFT) |
-	    ((ia64_get_rr(start) >> 8) << SH_PTC_0_RID_SHFT) |
-	    (1UL << SH_PTC_0_START_SHFT);
-
-	ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
-	ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
+	shub1 = is_shub1();
+	if (shub1) {
+		data0 = (1UL << SH1_PTC_0_A_SHFT) |
+		    	(nbits << SH1_PTC_0_PS_SHFT) |
+		    	((ia64_get_rr(start) >> 8) << SH1_PTC_0_RID_SHFT) |
+		    	(1UL << SH1_PTC_0_START_SHFT);
+		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
+		ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
+	} else {
+		data0 = (1UL << SH2_PTC_A_SHFT) |
+			(nbits << SH2_PTC_PS_SHFT) |
+		    	(1UL << SH2_PTC_START_SHFT);
+		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + 
+			((ia64_get_rr(start) >> 8) << SH2_PTC_RID_SHFT) );
+		ptc1 = NULL;
+	}
+	
 
 	mynasid = get_nasid();
 
 	spin_lock_irqsave(&sn2_global_ptc_lock, flags);
 
 	do {
-		data1 = start | (1UL << SH_PTC_1_START_SHFT);
+		if (shub1)
+			data1 = start | (1UL << SH1_PTC_1_START_SHFT);
+		else
+			data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
 		for (i = 0; i < nix; i++) {
 			nasid = nasids[i];
-			if (likely(nasid == mynasid)) {
+			if (unlikely(nasid == mynasid)) {
 				ia64_ptcga(start, nbits << 2);
 				ia64_srlz_i();
 			} else {
 				ptc0 = CHANGE_NASID(nasid, ptc0);
-				ptc1 = CHANGE_NASID(nasid, ptc1);
+				if (ptc1)
+					ptc1 = CHANGE_NASID(nasid, ptc1);
 				pio_atomic_phys_write_mmrs(ptc0, data0, ptc1,
 							   data1);
 				flushed = 1;
@@ -159,8 +173,8 @@
 
 		if (flushed
 		    && (wait_piowc() &
-			SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK)) {
-			sn2_ptc_deadlock_recovery(data0, data1);
+			SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK)) {
+			sn2_ptc_deadlock_recovery(ptc0, data0, ptc1, data1);
 		}
 
 		start += (1UL << nbits);
@@ -179,18 +193,19 @@
  * TLB flush transaction.  The recovery sequence is somewhat tricky & is
  * coded in assembly language.
  */
-void sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1)
+void sn2_ptc_deadlock_recovery(volatile unsigned long *ptc0, unsigned long data0,
+	volatile unsigned long *ptc1, unsigned long data1)
 {
-	extern void sn2_ptc_deadlock_recovery_core(long *, long, long *, long,
-						   long *);
+	extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
+	        volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long);
 	int cnode, mycnode, nasid;
-	long *ptc0, *ptc1, *piows;
+	volatile unsigned long *piows;
+	volatile unsigned long zeroval;
 
 	sn2_ptc_deadlock_count++;
 
-	ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
-	ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
-	piows = (long *)pda->pio_write_status_addr;
+	piows = pda->pio_write_status_addr;
+	zeroval = pda->pio_write_status_val;
 
 	mycnode = numa_node_id();
 
@@ -199,8 +214,9 @@
 			continue;
 		nasid = cnodeid_to_nasid(cnode);
 		ptc0 = CHANGE_NASID(nasid, ptc0);
-		ptc1 = CHANGE_NASID(nasid, ptc1);
-		sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows);
+		if (ptc1)
+			ptc1 = CHANGE_NASID(nasid, ptc1);
+		sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
 	}
 }
 
diff -Nru a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
--- a/arch/ia64/sn/kernel/sn2/timer.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/sn2/timer.c	2005-01-05 18:28:29 -08:00
@@ -15,7 +15,6 @@
 #include <asm/hw_irq.h>
 #include <asm/system.h>
 
-#include "shub.h"
 #include <asm/sn/leds.h>
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/clksupport.h>
@@ -26,12 +25,12 @@
 	.drift = -1,
 	.shift = 10,
 	.mask = (1LL << 55) - 1,
-	.source = TIME_SOURCE_MMIO64,
-	.addr = RTC_COUNTER_ADDR
+	.source = TIME_SOURCE_MMIO64
 };
 
 void __init sn_timer_init(void)
 {
 	sn2_interpolator.frequency = sn_rtc_cycles_per_second;
+	sn2_interpolator.addr = RTC_COUNTER_ADDR;
 	register_time_interpolator(&sn2_interpolator);
 }
diff -Nru a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
--- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c	2005-01-05 18:28:29 -08:00
+++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c	2005-01-05 18:28:29 -08:00
@@ -34,7 +34,6 @@
 
 #include <linux/interrupt.h>
 #include <asm/sn/pda.h>
-#include "shub.h"
 #include <asm/sn/leds.h>
 
 extern void sn_lb_int_war_check(void);
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/hardirq.h	2005-01-05 18:28:29 -08:00
@@ -34,4 +34,6 @@
 
 extern void __iomem *ipi_base_addr;
 
+void ack_bad_irq(unsigned int irq);
+
 #endif /* _ASM_IA64_HARDIRQ_H */
diff -Nru a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
--- a/include/asm-ia64/hw_irq.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/hw_irq.h	2005-01-05 18:28:29 -08:00
@@ -96,13 +96,13 @@
  * Default implementations for the irq-descriptor API:
  */
 
-extern irq_desc_t _irq_desc[NR_IRQS];
+extern irq_desc_t irq_desc[NR_IRQS];
 
 #ifndef CONFIG_IA64_GENERIC
 static inline irq_desc_t *
 __ia64_irq_desc (unsigned int irq)
 {
-	return _irq_desc + irq;
+	return irq_desc + irq;
 }
 
 static inline ia64_vector
diff -Nru a/include/asm-ia64/kregs.h b/include/asm-ia64/kregs.h
--- a/include/asm-ia64/kregs.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/kregs.h	2005-01-05 18:28:29 -08:00
@@ -14,6 +14,7 @@
  */
 #define IA64_KR_IO_BASE		0	/* ar.k0: legacy I/O base address */
 #define IA64_KR_TSSD		1	/* ar.k1: IVE uses this as the TSSD */
+#define IA64_KR_PA_CPU_INFO	3	/* ar.k3: phys addr of this cpu's cpu_info struct */
 #define IA64_KR_CURRENT_STACK	4	/* ar.k4: what's mapped in IA64_TR_CURRENT_STACK */
 #define IA64_KR_FPU_OWNER	5	/* ar.k5: fpu-owner (UP only, at the moment) */
 #define IA64_KR_CURRENT		6	/* ar.k6: "current" task pointer */
diff -Nru a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
--- a/include/asm-ia64/mca.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/mca.h	2005-01-05 18:28:29 -08:00
@@ -5,6 +5,7 @@
  * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander (vijay@engr.sgi.com)
  * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+ * Copyright (C) Russ Anderson (rja@sgi.com)
  */
 
 #ifndef _ASM_IA64_MCA_H
@@ -48,17 +49,6 @@
 	IA64_MCA_RENDEZ_CHECKIN_DONE	=	0x1
 };
 
-/* the following data structure is used for TLB error recovery purposes */
-extern struct ia64_mca_tlb_info {
-	u64	cr_lid;
-	u64	percpu_paddr;
-	u64	ptce_base;
-	u32	ptce_count[2];
-	u32	ptce_stride[2];
-	u64	pal_paddr;
-	u64	pal_base;
-} ia64_mca_tlb_list[NR_CPUS];
-
 /* Information maintained by the MC infrastructure */
 typedef struct ia64_mc_info_s {
 	u64		imi_mca_handler;
@@ -111,6 +101,18 @@
 						 * back to SAL from OS after MCA handling.
 						 */
 } ia64_mca_os_to_sal_state_t;
+
+#define IA64_MCA_STACK_SIZE 	1024
+#define IA64_MCA_STACK_SIZE_BYTES 	(1024 * 8)
+#define IA64_MCA_BSPSTORE_SIZE 	1024
+
+typedef struct ia64_mca_cpu_s {
+	u64	ia64_mca_stack[IA64_MCA_STACK_SIZE] 		__attribute__((aligned(16)));
+	u64	ia64_mca_proc_state_dump[512] 			__attribute__((aligned(16)));
+	u64	ia64_mca_stackframe[32]				__attribute__((aligned(16)));
+	u64	ia64_mca_bspstore[IA64_MCA_BSPSTORE_SIZE] 	__attribute__((aligned(16)));
+	u64	ia64_init_stack[KERNEL_STACK_SIZE] 		__attribute__((aligned(16)));
+} ia64_mca_cpu_t;
 
 extern void ia64_mca_init(void);
 extern void ia64_os_mca_dispatch(void);
diff -Nru a/include/asm-ia64/mca_asm.h b/include/asm-ia64/mca_asm.h
--- a/include/asm-ia64/mca_asm.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/mca_asm.h	2005-01-05 18:28:29 -08:00
@@ -47,6 +47,37 @@
 	dep	addr	= temp, addr, 61, 3
 
 /*
+ * This macro gets the physical address of this cpu's cpuinfo structure.
+ */
+#define GET_PERCPU_PADDR(reg)							\
+	mov	reg	= ar.k3;;						\
+	addl	reg	= IA64_CPUINFO_PERCPU_PADDR,reg
+
+/*
+ * This macro gets the physical address of this cpu's MCA save structure.
+ */
+#define GET_CPUINFO_MCA_PADDR(reg)						\
+	mov	reg	= ar.k3;;						\
+	addl	reg	= IA64_CPUINFO_PA_MCA_INFO,reg;;			\
+	ld8	reg	= [reg]
+
+#define	GET_MCA_BSPSTORE(reg)							\
+	GET_CPUINFO_MCA_PADDR(reg);;						\
+	addl	reg	= IA64_MCA_BSPSTORE,reg
+
+#define	GET_MCA_STACKFRAME(reg)							\
+	GET_CPUINFO_MCA_PADDR(reg);;						\
+	addl	reg	= IA64_MCA_STACKFRAME,reg
+
+#define	GET_MCA_STACK(reg)							\
+	GET_CPUINFO_MCA_PADDR(reg);;						\
+	addl	reg	= IA64_MCA_STACK,reg
+
+#define	GET_MCA_DUMP_PADDR(reg)							\
+	GET_CPUINFO_MCA_PADDR(reg);;						\
+	addl	reg	= IA64_MCA_PROC_STATE_DUMP,reg
+
+/*
  * This macro jumps to the instruction at the given virtual address
  * and starts execution in physical mode with all the address
  * translations turned off.
diff -Nru a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h
--- a/include/asm-ia64/msi.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/msi.h	2005-01-05 18:28:29 -08:00
@@ -12,7 +12,6 @@
 static inline void set_intr_gate (int nr, void *func) {}
 #define IO_APIC_VECTOR(irq)	(irq)
 #define ack_APIC_irq		ia64_eoi
-#define irq_desc		_irq_desc
 #define cpu_mask_to_apicid(mask) cpu_physical_id(first_cpu(mask))
 #define MSI_DEST_MODE		MSI_PHYSICAL_MODE
 #define MSI_TARGET_CPU	((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/processor.h	2005-01-05 18:28:29 -08:00
@@ -151,9 +151,12 @@
 	__u64 itc_freq;		/* frequency of ITC counter */
 	__u64 proc_freq;	/* frequency of processor */
 	__u64 cyc_per_usec;	/* itc_freq/1000000 */
+	__u64 percpu_paddr;
 	__u64 ptce_base;
 	__u32 ptce_count[2];
 	__u32 ptce_stride[2];
+	__u64 pal_paddr;
+	__u64 pal_base;
 	struct task_struct *ksoftirqd;	/* kernel softirq daemon for this CPU */
 
 #ifdef CONFIG_SMP
@@ -174,6 +177,7 @@
 #ifdef CONFIG_NUMA
 	struct ia64_node_data *node_data;
 #endif
+	__u64 *ia64_pa_mca_data;	/* prt to MCA/INIT processor state */
 };
 
 DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sal.h	2005-01-05 18:28:29 -08:00
@@ -325,6 +325,10 @@
 	efi_guid_t platform_guid;	/* Unique OEM Platform ID */
 } sal_log_record_header_t;
 
+#define sal_log_severity_recoverable	0
+#define sal_log_severity_fatal		1
+#define sal_log_severity_corrected	2
+
 /* Definition of log section header structures */
 typedef struct sal_log_sec_header {
     efi_guid_t guid;			/* Unique Section ID */
diff -Nru a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h
--- a/include/asm-ia64/signal.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/signal.h	2005-01-05 18:28:29 -08:00
@@ -177,6 +177,8 @@
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
+void set_sigdelayed(pid_t pid, int signo, int code, void __user *addr);
+
 #endif /* __KERNEL__ */
 
 # endif /* !__ASSEMBLY__ */
diff -Nru a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h
--- a/include/asm-ia64/sn/addrs.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/addrs.h	2005-01-05 18:28:29 -08:00
@@ -9,204 +9,175 @@
 #ifndef _ASM_IA64_SN_ADDRS_H
 #define _ASM_IA64_SN_ADDRS_H
 
+#include <asm/percpu.h>
+#include <asm/sn/types.h>
+#include <asm/sn/pda.h>
 
-/* McKinley Address Format:
- *
- *   4 4       3 3  3 3
- *   9 8       8 7  6 5             0
- *  +-+---------+----+--------------+
- *  |0| Node ID | AS | Node Offset  |
- *  +-+---------+----+--------------+
+/*
+ *  Memory/SHUB Address Format:
+ *  +-+---------+--+--------------+
+ *  |0|  NASID  |AS| NodeOffset   |
+ *  +-+---------+--+--------------+
  *
- *   Node ID: If bit 38 = 1, is ICE, else is SHUB
- *   AS: Address Space Identifier. Used only if bit 38 = 0.
- *     b'00: Local Resources and MMR space
- *           bit 35
+ *  NASID: (low NASID bit is 0) Memory and SHUB MMRs
+ *   AS: 2-bit Address Space Identifier. Used only if low NASID bit is 0
+ *     00: Local Resources and MMR space
+ *           Top bit of NodeOffset
  *               0: Local resources space
  *                  node id:
  *                        0: IA64/NT compatibility space
  *                        2: Local MMR Space
  *                        4: Local memory, regardless of local node id
  *               1: Global MMR space
- *     b'01: GET space.
- *     b'10: AMO space.
- *     b'11: Cacheable memory space.
+ *     01: GET space.
+ *     10: AMO space.
+ *     11: Cacheable memory space.
  *
  *   NodeOffset: byte offset
+ *
+ *
+ *  TIO address format:
+ *  +-+----------+--+--------------+
+ *  |0|  NASID   |AS| Nodeoffset   |
+ *  +-+----------+--+--------------+
+ *
+ *  NASID: (low NASID bit is 1) TIO
+ *   AS: 2-bit Chiplet Identifier
+ *     00: TIO LB (Indicates TIO MMR access.)
+ *     01: TIO ICE (indicates coretalk space access.)
+ * 
+ *   NodeOffset: top bit must be set.
+ *
+ *
+ * Note that in both of the above address formats, the low
+ * NASID bit indicates if the reference is to the SHUB or TIO MMRs.
  */
 
-/* TIO address format:
- *  4 4        3 3 3 3 3             0
- *  9 8        8 7 6 5 4
- * +-+----------+-+---+--------------+
- * |0| Node ID  |0|CID| Node offset  |
- * +-+----------+-+---+--------------+
- *
- * Node ID: if bit 38 == 1, is ICE.
- * Bit 37: Must be zero.
- * CID: Chiplet ID:
- *     b'01: TIO LB (Indicates TIO MMR access.)
- *     b'11: TIO ICE (indicates coretalk space access.)
- * Node offset: byte offest.
+
+/*
+ * Define basic shift & mask constants for manipulating NASIDs and AS values.
  */
+#define NASID_BITMASK		(pda->nasid_bitmask)
+#define NASID_SHIFT		(pda->nasid_shift)
+#define AS_SHIFT		(pda->as_shift)
+#define AS_BITMASK		0x3UL
+
+#define NASID_MASK              ((u64)NASID_BITMASK << NASID_SHIFT)
+#define AS_MASK			((u64)AS_BITMASK << AS_SHIFT)
+#define REGION_BITS		0xe000000000000000UL
+
 
 /*
- * Note that in both of the above address formats, bit
- * 35 set indicates that the reference is to the 
- * shub or tio MMRs.
- */
-
-#ifndef __ASSEMBLY__
-typedef union ia64_sn2_pa {
-	struct {
-		unsigned long off  : 36;
-		unsigned long as   : 2;
-		unsigned long nasid: 11;
-		unsigned long fill : 15;
-	} f;
-	unsigned long l;
-	void *p;
-} ia64_sn2_pa_t;
-#endif
-
-#define TO_PHYS_MASK		0x0001ffcfffffffffUL	/* Note - clear AS bits */
-
-
-/* Regions determined by AS */
-#define LOCAL_MMR_SPACE		0xc000008000000000UL	/* Local MMR space */
-#define LOCAL_PHYS_MMR_SPACE	0x8000008000000000UL	/* Local PhysicalMMR space */
-#define LOCAL_MEM_SPACE		0xc000010000000000UL	/* Local Memory space */
-/* It so happens that setting bit 35 indicates a reference to the SHUB or TIO
- * MMR space.  
- */
-#define GLOBAL_MMR_SPACE	0xc000000800000000UL	/* Global MMR space */
-#define TIO_MMR_SPACE		0xc000000800000000UL	/* TIO MMR space */
-#define ICE_MMR_SPACE		0xc000000000000000UL	/* ICE MMR space */
-#define GLOBAL_PHYS_MMR_SPACE	0x0000000800000000UL	/* Global Physical MMR space */
-#define GET_SPACE		0xe000001000000000UL	/* GET space */
-#define AMO_SPACE		0xc000002000000000UL	/* AMO space */
-#define CACHEABLE_MEM_SPACE	0xe000003000000000UL	/* Cacheable memory space */
-#define UNCACHED                0xc000000000000000UL	/* UnCacheable memory space */
-#define UNCACHED_PHYS           0x8000000000000000UL	/* UnCacheable physical memory space */
-
-#define PHYS_MEM_SPACE		0x0000003000000000UL	/* physical memory space */
-
-/* SN2 address macros */
-/* NID_SHFT has the right value for both SHUB and TIO addresses.*/
-#define NID_SHFT		38
-#define LOCAL_MMR_ADDR(a)	(UNCACHED | LOCAL_MMR_SPACE | (a))
-#define LOCAL_MMR_PHYS_ADDR(a)	(UNCACHED_PHYS | LOCAL_PHYS_MMR_SPACE | (a))
-#define LOCAL_MEM_ADDR(a)	(LOCAL_MEM_SPACE | (a))
-#define REMOTE_ADDR(n,a)	((((unsigned long)(n))<<NID_SHFT) | (a))
-#define GLOBAL_MMR_ADDR(n,a)	(UNCACHED | GLOBAL_MMR_SPACE | REMOTE_ADDR(n,a))
-#define GLOBAL_MMR_PHYS_ADDR(n,a) (UNCACHED_PHYS | GLOBAL_PHYS_MMR_SPACE | REMOTE_ADDR(n,a))
-#define GET_ADDR(n,a)		(GET_SPACE | REMOTE_ADDR(n,a))
-#define AMO_ADDR(n,a)		(UNCACHED | AMO_SPACE | REMOTE_ADDR(n,a))
-#define GLOBAL_MEM_ADDR(n,a)	(CACHEABLE_MEM_SPACE | REMOTE_ADDR(n,a))
+ * AS values. These are the same on both SHUB1 & SHUB2.
+ */
+#define AS_GET_VAL		1UL
+#define AS_AMO_VAL		2UL
+#define AS_CAC_VAL		3UL
+#define AS_GET_SPACE		(AS_GET_VAL << AS_SHIFT)
+#define AS_AMO_SPACE		(AS_AMO_VAL << AS_SHIFT)
+#define AS_CAC_SPACE		(AS_CAC_VAL << AS_SHIFT)
 
-/* non-II mmr's start at top of big window space (4G) */
-#define BWIN_TOP		0x0000000100000000UL
 
 /*
- * general address defines - for code common to SN0/SN1/SN2
+ * Base addresses for various address ranges.
+ */
+#define CACHED			0xe000000000000000UL
+#define UNCACHED                0xc000000000000000UL
+#define UNCACHED_PHYS           0x8000000000000000UL
+
+
+/* 
+ * Virtual Mode Local & Global MMR space.  
  */
-#define CAC_BASE		CACHEABLE_MEM_SPACE			/* cacheable memory space */
-#define IO_BASE			(UNCACHED | GLOBAL_MMR_SPACE)		/* lower 4G maps II's XIO space */
-#define TIO_BASE		(UNCACHED | ICE_MMR_SPACE)		/* lower 4G maps TIO space */
-#define AMO_BASE		(UNCACHED | AMO_SPACE)			/* fetch & op space */
-#define MSPEC_BASE		AMO_BASE				/* fetch & op space */
-#define UNCAC_BASE		(UNCACHED | CACHEABLE_MEM_SPACE)	/* uncached global memory */
-#define GET_BASE		GET_SPACE				/* momentarily coherent remote mem. */
-#define CALIAS_BASE             LOCAL_CACHEABLE_BASE			/* cached node-local memory */
-#define UALIAS_BASE             (UNCACHED | LOCAL_CACHEABLE_BASE)	/* uncached node-local memory */
-
-#define TO_PHYS(x)              (              ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)               (CAC_BASE    | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)             (UNCAC_BASE  | ((x) & TO_PHYS_MASK))
-#define TO_MSPEC(x)             (MSPEC_BASE  | ((x) & TO_PHYS_MASK))
-#define TO_GET(x)		(GET_BASE    | ((x) & TO_PHYS_MASK))
-#define TO_CALIAS(x)            (CALIAS_BASE | TO_NODE_ADDRSPACE(x))
-#define TO_UALIAS(x)            (UALIAS_BASE | TO_NODE_ADDRSPACE(x))
-#define NODE_SIZE_BITS		36	/* node offset : bits <35:0> */
-#define BWIN_SIZE_BITS		29	/* big window size: 512M */
-#define TIO_BWIN_SIZE_BITS	30	/* big window size: 1G */
-#define NASID_BITS		11	/* bits <48:38> */
-#define NASID_BITMASK		(0x7ffULL)
-#define NASID_SHFT		NID_SHFT
-#define NASID_META_BITS		0	/* ???? */
-#define NASID_LOCAL_BITS	7	/* same router as SN1 */
-
-#define NODE_ADDRSPACE_SIZE     (1UL << NODE_SIZE_BITS)
-#define NASID_MASK              ((uint64_t) NASID_BITMASK << NASID_SHFT)
-#define NASID_GET(_pa)          (int) (((uint64_t) (_pa) >>            \
-                                        NASID_SHFT) & NASID_BITMASK)
-#define PHYS_TO_DMA(x)          ( ((x & NASID_MASK) >> 2) |             \
-                                  (x & (NODE_ADDRSPACE_SIZE - 1)) )
-
-/*
- * This address requires a chiplet id in bits 38-39.  For DMA to memory,
- * the chiplet id is zero.  If we implement TIO-TIO dma, we might need
- * to insert a chiplet id into this macro.  However, it is our belief
- * right now that this chiplet id will be ICE, which is also zero.
- */
-#define PHYS_TO_TIODMA(x)     ( ((x & NASID_MASK) << 2) |             \
-                                 (x & (NODE_ADDRSPACE_SIZE - 1)) )
-
-#define CHANGE_NASID(n,x)	({ia64_sn2_pa_t _v; _v.l = (long) (x); _v.f.nasid = n; _v.p;})
-
-
-#ifndef __ASSEMBLY__
-#define NODE_SWIN_BASE(nasid, widget)                                   \
-        ((widget == 0) ? NODE_BWIN_BASE((nasid), SWIN0_BIGWIN)          \
-        : RAW_NODE_SWIN_BASE(nasid, widget))
-#else
-#define NODE_SWIN_BASE(nasid, widget) \
-     (NODE_IO_BASE(nasid) + ((uint64_t) (widget) << SWIN_SIZE_BITS))
-#define LOCAL_SWIN_BASE(widget) \
-	(UNCACHED | LOCAL_MMR_SPACE | (((uint64_t) (widget) << SWIN_SIZE_BITS)))
-#endif /* __ASSEMBLY__ */
+#define SH1_LOCAL_MMR_OFFSET	0x8000000000UL
+#define SH2_LOCAL_MMR_OFFSET	0x0200000000UL
+#define LOCAL_MMR_OFFSET	(is_shub2() ? SH2_LOCAL_MMR_OFFSET : SH1_LOCAL_MMR_OFFSET)
+#define LOCAL_MMR_SPACE		(UNCACHED | LOCAL_MMR_OFFSET)
+#define LOCAL_PHYS_MMR_SPACE	(UNCACHED_PHYS | LOCAL_MMR_OFFSET)
+
+#define SH1_GLOBAL_MMR_OFFSET	0x0800000000UL
+#define SH2_GLOBAL_MMR_OFFSET	0x0300000000UL
+#define GLOBAL_MMR_OFFSET	(is_shub2() ? SH2_GLOBAL_MMR_OFFSET : SH1_GLOBAL_MMR_OFFSET)
+#define GLOBAL_MMR_SPACE	(UNCACHED | GLOBAL_MMR_OFFSET)
 
 /*
- * The following definitions pertain to the IO special address
- * space.  They define the location of the big and little windows
- * of any given node.
+ * Physical mode addresses
  */
+#define GLOBAL_PHYS_MMR_SPACE	(UNCACHED_PHYS | GLOBAL_MMR_OFFSET)
 
-#define BWIN_SIZE               (1UL << BWIN_SIZE_BITS)
-#define BWIN_SIZEMASK           (BWIN_SIZE - 1)
-#define BWIN_WIDGET_MASK        0x7
-#define NODE_BWIN_BASE0(nasid)  (NODE_IO_BASE(nasid) + BWIN_SIZE)
-#define NODE_BWIN_BASE(nasid, bigwin)   (NODE_BWIN_BASE0(nasid) +       \
-                        ((uint64_t) (bigwin) << BWIN_SIZE_BITS))
 
-#define BWIN_WIDGETADDR(addr)   ((addr) & BWIN_SIZEMASK)
-#define BWIN_WINDOWNUM(addr)    (((addr) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK)
+/*
+ * Clear region & AS bits.
+ */
+#define TO_PHYS_MASK		(~(REGION_BITS | AS_MASK))
 
-#define TIO_BWIN_WINDOW_SELECT_MASK 0x7
-#define TIO_BWIN_WINDOWNUM(addr)    (((addr) >> TIO_BWIN_SIZE_BITS) & TIO_BWIN_WINDOW_SELECT_MASK)
 
+/*
+ * Misc NASID manipulation.
+ */
+#define NASID_SPACE(n)		((u64)(n) << NASID_SHIFT)
+#define REMOTE_ADDR(n,a)	(NASID_SPACE(n) | (a))
+#define NODE_OFFSET(x)		((x) & (NODE_ADDRSPACE_SIZE - 1))
+#define NODE_ADDRSPACE_SIZE     (1UL << AS_SHIFT)
+#define NASID_GET(x)		(int) (((u64) (x) >> NASID_SHIFT) & NASID_BITMASK)
+#define LOCAL_MMR_ADDR(a)	(LOCAL_MMR_SPACE | (a))
+#define GLOBAL_MMR_ADDR(n,a)	(GLOBAL_MMR_SPACE | REMOTE_ADDR(n,a))
+#define GLOBAL_MMR_PHYS_ADDR(n,a) (GLOBAL_PHYS_MMR_SPACE | REMOTE_ADDR(n,a))
+#define GLOBAL_CAC_ADDR(n,a)	(CAC_BASE | REMOTE_ADDR(n,a))
+#define CHANGE_NASID(n,x)	((void *)(((u64)(x) & ~NASID_MASK) | NASID_SPACE(n)))
 
-#ifndef __ASSEMBLY__
-#include <asm/sn/types.h>
-#endif 
+
+/* non-II mmr's start at top of big window space (4G) */
+#define BWIN_TOP		0x0000000100000000UL
 
 /*
- * The following macros are used to index to the beginning of a specific
- * node's address space.
+ * general address defines
  */
+#define CAC_BASE		(CACHED   | AS_CAC_SPACE)
+#define AMO_BASE		(UNCACHED | AS_AMO_SPACE)
+#define GET_BASE		(CACHED   | AS_GET_SPACE)
 
-#define NODE_OFFSET(_n)		((uint64_t) (_n) << NASID_SHFT)
+/*
+ * Convert Memory addresses between various addressing modes.
+ */
+#define TO_PHYS(x)		(TO_PHYS_MASK & (x))
+#define TO_CAC(x)		(CAC_BASE     | TO_PHYS(x))
+#define TO_AMO(x)		(AMO_BASE     | TO_PHYS(x))
+#define TO_GET(x)		(GET_BASE     | TO_PHYS(x))
 
-#define NODE_CAC_BASE(_n)	(CAC_BASE  + NODE_OFFSET(_n))
-#define NODE_HSPEC_BASE(_n)	(HSPEC_BASE + NODE_OFFSET(_n))
-#define NODE_IO_BASE(_n)	(IO_BASE    + NODE_OFFSET(_n))
-#define NODE_MSPEC_BASE(_n)	(MSPEC_BASE + NODE_OFFSET(_n))
-#define NODE_UNCAC_BASE(_n)	(UNCAC_BASE + NODE_OFFSET(_n))
 
-#define TO_NODE_CAC(_n, _x)	(NODE_CAC_BASE(_n) | ((_x) & TO_PHYS_MASK))
+/*
+ * Covert from processor physical address to II/TIO physical address:
+ *	II - squeeze out the AS bits
+ *	TIO- requires a chiplet id in bits 38-39.  For DMA to memory,
+ *           the chiplet id is zero.  If we implement TIO-TIO dma, we might need
+ *           to insert a chiplet id into this macro.  However, it is our belief
+ *           right now that this chiplet id will be ICE, which is also zero.
+ */
+#define PHYS_TO_TIODMA(x)	( (((u64)(x) & NASID_MASK) << 2) | NODE_OFFSET(x))
+#define PHYS_TO_DMA(x)          ( (((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x))
+
+
+/*
+ * The following definitions pertain to the IO special address
+ * space.  They define the location of the big and little windows
+ * of any given node.
+ */
+#define BWIN_SIZE_BITS			29	/* big window size: 512M */
+#define TIO_BWIN_SIZE_BITS		30	/* big window size: 1G */
+#define NODE_SWIN_BASE(n, w)		((w == 0) ? NODE_BWIN_BASE((n), SWIN0_BIGWIN) \
+		: RAW_NODE_SWIN_BASE(n, w))
+#define NODE_IO_BASE(n)			(GLOBAL_MMR_SPACE | NASID_SPACE(n))
+#define BWIN_SIZE			(1UL << BWIN_SIZE_BITS)
+#define NODE_BWIN_BASE0(n)		(NODE_IO_BASE(n) + BWIN_SIZE)
+#define NODE_BWIN_BASE(n, w)		(NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS))
+#define RAW_NODE_SWIN_BASE(n, w)	(NODE_IO_BASE(n) + ((u64) (w) << SWIN_SIZE_BITS))
+#define BWIN_WIDGET_MASK		0x7
+#define BWIN_WINDOWNUM(x)		(((x) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK)
+
+#define TIO_BWIN_WINDOW_SELECT_MASK	0x7
+#define TIO_BWIN_WINDOWNUM(x)		(((x) >> TIO_BWIN_SIZE_BITS) & TIO_BWIN_WINDOW_SELECT_MASK)
 
-#define RAW_NODE_SWIN_BASE(nasid, widget)				\
-	(NODE_IO_BASE(nasid) + ((uint64_t) (widget) << SWIN_SIZE_BITS))
 
 
 /*
@@ -215,15 +186,12 @@
  * of any given node.
  */
 
-#define SWIN_SIZE_BITS		24
-#define SWIN_SIZE		(1UL << 24)
-#define	SWIN_SIZEMASK		(SWIN_SIZE - 1)
-#define	SWIN_WIDGET_MASK	0xF
-
-#define TIO_SWIN_SIZE_BITS	28
-#define TIO_SWIN_SIZE		(1UL << 28)
-#define TIO_SWIN_SIZEMASK	(SWIN_SIZE - 1)
-#define TIO_SWIN_WIDGET_MASK	0x3
+#define SWIN_SIZE_BITS			24
+#define	SWIN_WIDGET_MASK		0xF
+
+#define TIO_SWIN_SIZE_BITS		28
+#define TIO_SWIN_SIZE			(1UL << TIO_SWIN_SIZE_BITS)
+#define TIO_SWIN_WIDGET_MASK		0x3
 
 /*
  * Convert smallwindow address to xtalk address.
@@ -231,82 +199,39 @@
  * 'addr' can be physical or virtual address, but will be converted
  * to Xtalk address in the range 0 -> SWINZ_SIZEMASK
  */
-#define	SWIN_WIDGETNUM(addr)	(((addr)  >> SWIN_SIZE_BITS) & SWIN_WIDGET_MASK)
+#define	SWIN_WIDGETNUM(x)		(((x)  >> SWIN_SIZE_BITS) & SWIN_WIDGET_MASK)
+#define TIO_SWIN_WIDGETNUM(x)		(((x)  >> TIO_SWIN_SIZE_BITS) & TIO_SWIN_WIDGET_MASK)
 
-#define TIO_SWIN_WIDGETNUM(addr)	(((addr)  >> TIO_SWIN_SIZE_BITS) & TIO_SWIN_WIDGET_MASK)
 
 /*
  * The following macros produce the correct base virtual address for
- * the hub registers.  The LOCAL_HUB_* macros produce the appropriate
- * address for the local registers.  The REMOTE_HUB_* macro produce
+ * the hub registers. The REMOTE_HUB_* macro produce
  * the address for the specified hub's registers.  The intent is
  * that the appropriate PI, MD, NI, or II register would be substituted
- * for _x.
- */
-
-
-/*
- * SN2 has II mmr's located inside small window space.
- * As all other non-II mmr's located at the top of big window
- * space.
- */
-#define REMOTE_HUB_BASE(_x)						\
-        (UNCACHED | GLOBAL_MMR_SPACE |                                  \
-        (((~(_x)) & BWIN_TOP)>>8)    |                                       \
-        (((~(_x)) & BWIN_TOP)>>9)    | (_x))
-
-#define REMOTE_HUB(_n, _x)						\
-	((uint64_t *)(REMOTE_HUB_BASE(_x) | ((((long)(_n))<<NASID_SHFT))))
-
-
-/*
- * WARNING:
+ * for x.
+ *
+ *   WARNING:
  *	When certain Hub chip workaround are defined, it's not sufficient
  *	to dereference the *_HUB_ADDR() macros.  You should instead use
  *	HUB_L() and HUB_S() if you must deal with pointers to hub registers.
  *	Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S().
  *	They're always safe.
  */
-/*
- * LOCAL_HUB_ADDR doesn't need to be changed for TIO, since, by definition,
- * there are no "local" TIOs.
- */
-#define LOCAL_HUB_ADDR(_x)							\
-	(((_x) & BWIN_TOP) ? ((volatile uint64_t *)(LOCAL_MMR_ADDR(_x)))		\
-	: ((volatile uint64_t *)(IALIAS_BASE + (_x))))
-#define REMOTE_HUB_ADDR(_n, _x)						\
-	((_n & 1) ?							\
+#define REMOTE_HUB_ADDR(n,x)						\
+	((n & 1) ?							\
 	/* TIO: */							\
-	((volatile uint64_t *)(GLOBAL_MMR_ADDR(_n, _x)))				\
+	((volatile u64 *)(GLOBAL_MMR_ADDR(n,x)))			\
 	: /* SHUB: */							\
-	(((_x) & BWIN_TOP) ? ((volatile uint64_t *)(GLOBAL_MMR_ADDR(_n, _x)))	\
-	: ((volatile uint64_t *)(NODE_SWIN_BASE(_n, 1) + 0x800000 + (_x)))))
-
-#ifndef __ASSEMBLY__
+	(((x) & BWIN_TOP) ? ((volatile u64 *)(GLOBAL_MMR_ADDR(n,x)))\
+	: ((volatile u64 *)(NODE_SWIN_BASE(n,1) + 0x800000 + (x)))))
 
-#define HUB_L(_a)			(*((volatile typeof(*_a) *)_a))
-#define	HUB_S(_a, _d)			(*((volatile typeof(*_a) *)_a) = (_d))
 
-#define LOCAL_HUB_L(_r)			HUB_L(LOCAL_HUB_ADDR(_r))
-#define LOCAL_HUB_S(_r, _d)		HUB_S(LOCAL_HUB_ADDR(_r), (_d))
-#define REMOTE_HUB_L(_n, _r)		HUB_L(REMOTE_HUB_ADDR((_n), (_r)))
-#define REMOTE_HUB_S(_n, _r, _d)	HUB_S(REMOTE_HUB_ADDR((_n), (_r)), (_d))
-#define REMOTE_HUB_PI_L(_n, _sn, _r)	HUB_L(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)))
-#define REMOTE_HUB_PI_S(_n, _sn, _r, _d) HUB_S(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)), (_d))
 
-#endif /* __ASSEMBLY__ */
-
-/*
- * The following macros are used to get to a hub/bridge register, given
- * the base of the register space.
- */
-#define HUB_REG_PTR(_base, _off)	\
-	(volatile uint64_t *)((unsigned long)(_base) + (__psunsigned_t)(_off)))
+#define HUB_L(x)			(*((volatile typeof(*x) *)x))
+#define	HUB_S(x,d)			(*((volatile typeof(*x) *)x) = (d))
 
-#define HUB_REG_PTR_L(_base, _off)	\
-	HUB_L(HUB_REG_PTR((_base), (_off)))
+#define REMOTE_HUB_L(n, a)		HUB_L(REMOTE_HUB_ADDR((n), (a)))
+#define REMOTE_HUB_S(n, a, d)		HUB_S(REMOTE_HUB_ADDR((n), (a)), (d))
 
-#define HUB_REG_PTR_S(_base, _off, _data)	\
-	HUB_S(HUB_REG_PTR((_base), (_off)), (_data))
 
 #endif /* _ASM_IA64_SN_ADDRS_H */
diff -Nru a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h
--- a/include/asm-ia64/sn/arch.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/arch.h	2005-01-05 18:28:29 -08:00
@@ -20,7 +20,8 @@
  * Effectively, it's the maximum number of compact node ids (cnodeid_t).
  * This is not necessarily the same as MAX_NASIDS.
  */
-#define MAX_COMPACT_NODES       2048
+#define MAX_COMPACT_NODES	2048
+#define CPUS_PER_NODE		4
 
 extern void sn_flush_all_caches(long addr, long bytes);
 
diff -Nru a/include/asm-ia64/sn/klconfig.h b/include/asm-ia64/sn/klconfig.h
--- a/include/asm-ia64/sn/klconfig.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/klconfig.h	2005-01-05 18:28:29 -08:00
@@ -29,7 +29,7 @@
 } kl_config_hdr_t;
 
 
-#define NODE_OFFSET_TO_LBOARD(nasid,off)        (lboard_t*)(NODE_CAC_BASE(nasid) + (off))
+#define NODE_OFFSET_TO_LBOARD(nasid,off)        (lboard_t*)(GLOBAL_CAC_ADDR((nasid), (off)))
 
 /*
  * The KLCONFIG area is organized as a LINKED LIST of BOARDs. A BOARD
diff -Nru a/include/asm-ia64/sn/leds.h b/include/asm-ia64/sn/leds.h
--- a/include/asm-ia64/sn/leds.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/leds.h	2005-01-05 18:28:29 -08:00
@@ -9,6 +9,7 @@
 
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
+#include <asm/sn/shub_mmr.h>
 
 #define LED0		(LOCAL_MMR_ADDR(SH_REAL_JUNK_BUS_LED0))
 #define LED_CPU_SHIFT	16
diff -Nru a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h
--- a/include/asm-ia64/sn/pda.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/pda.h	2005-01-05 18:28:29 -08:00
@@ -37,17 +37,21 @@
 	 * Support for SN LEDs
 	 */
 	volatile short	*led_address;
+	u16		nasid_bitmask;
+	u8		shub2;
+	u8		nasid_shift;
+	u8		as_shift;
+	u8		shub_1_1_found;
 	u8		led_state;
 	u8		hb_state;	/* supports blinking heartbeat leds */
-	u8		shub_1_1_found;
 	unsigned int	hb_count;
 
 	unsigned int	idle_flag;
 	
 	volatile unsigned long *bedrock_rev_id;
 	volatile unsigned long *pio_write_status_addr;
+	unsigned long pio_write_status_val;
 	volatile unsigned long *pio_shub_war_cam_addr;
-	volatile unsigned long *mem_write_status_addr;
 
 	struct bteinfo_s *cpu_bte_if[BTES_PER_NODE];	/* cpu interface order */
 
@@ -76,7 +80,7 @@
  */
 DECLARE_PER_CPU(struct pda_s, pda_percpu);
 
-#define pda		(&__get_cpu_var(pda_percpu))
+#define pda		(&__ia64_per_cpu_var(pda_percpu))
 
 #define pdacpu(cpu)	(&per_cpu(pda_percpu, cpu))
 
@@ -84,5 +88,8 @@
  * Use this macro to test if shub 1.1 wars should be enabled
  */
 #define enable_shub_wars_1_1()	(pda->shub_1_1_found)
+
+#define is_shub2()	(pda->shub2)
+#define is_shub1()	(pda->shub2 == 0)
 
 #endif /* _ASM_IA64_SN_PDA_H */
diff -Nru a/include/asm-ia64/sn/rw_mmr.h b/include/asm-ia64/sn/rw_mmr.h
--- a/include/asm-ia64/sn/rw_mmr.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/rw_mmr.h	2005-01-05 18:28:29 -08:00
@@ -14,8 +14,8 @@
  * uncached physical addresses.
  * 	pio_phys_read_mmr  - read an MMR
  * 	pio_phys_write_mmr - write an MMR
- * 	pio_atomic_phys_write_mmrs - atomically write 2 MMRs with psr.ic=0
- * 		(interrupt collection)
+ * 	pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
+ *		Second MMR will be skipped if address is NULL
  *
  * Addresses passed to these routines should be uncached physical addresses
  * ie., 0x80000....
@@ -61,13 +61,14 @@
         asm volatile
             ("mov r2=psr;;"
              "rsm psr.i | psr.dt | psr.ic;;"
+	     "cmp.ne p9,p0=%2,r0;"
              "srlz.i;;"
              "st8.rel [%0]=%1;"
-             "st8.rel [%2]=%3;;"
+             "(p9) st8.rel [%2]=%3;;"
              "mov psr.l=r2;;"
              "srlz.i;;"
 	     :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2)
-             : "r2", "memory");
+             : "p9", "r2", "memory");
 }            
 
 #endif /* _ASM_IA64_SN_RW_MMR_H */
diff -Nru a/include/asm-ia64/sn/shub_mmr.h b/include/asm-ia64/sn/shub_mmr.h
--- a/include/asm-ia64/sn/shub_mmr.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/shub_mmr.h	2005-01-05 18:28:29 -08:00
@@ -14,117 +14,96 @@
 /*                        Register "SH_IPI_INT"                         */
 /*               SHub Inter-Processor Interrupt Registers               */
 /* ==================================================================== */
-#define SH_IPI_INT                               0x0000000110000380UL
-#define SH_IPI_INT_MASK                          0x8ff3ffffffefffffUL
-#define SH_IPI_INT_INIT                          0x0000000000000000UL
+#define SH1_IPI_INT                               0x0000000110000380
+#define SH2_IPI_INT                               0x0000000010000380
 
 /*   SH_IPI_INT_TYPE                                                    */
 /*   Description:  Type of Interrupt: 0=INT, 2=PMI, 4=NMI, 5=INIT       */
 #define SH_IPI_INT_TYPE_SHFT                     0
-#define SH_IPI_INT_TYPE_MASK                     0x0000000000000007UL
+#define SH_IPI_INT_TYPE_MASK                     0x0000000000000007
 
 /*   SH_IPI_INT_AGT                                                     */
 /*   Description:  Agent, must be 0 for SHub                            */
 #define SH_IPI_INT_AGT_SHFT                      3
-#define SH_IPI_INT_AGT_MASK                      0x0000000000000008UL
+#define SH_IPI_INT_AGT_MASK                      0x0000000000000008
 
 /*   SH_IPI_INT_PID                                                     */
 /*   Description:  Processor ID, same setting as on targeted McKinley  */
 #define SH_IPI_INT_PID_SHFT                      4
-#define SH_IPI_INT_PID_MASK                      0x00000000000ffff0UL
+#define SH_IPI_INT_PID_MASK                      0x00000000000ffff0
 
 /*   SH_IPI_INT_BASE                                                    */
 /*   Description:  Optional interrupt vector area, 2MB aligned          */
 #define SH_IPI_INT_BASE_SHFT                     21
-#define SH_IPI_INT_BASE_MASK                     0x0003ffffffe00000UL
+#define SH_IPI_INT_BASE_MASK                     0x0003ffffffe00000
 
 /*   SH_IPI_INT_IDX                                                     */
 /*   Description:  Targeted McKinley interrupt vector                   */
 #define SH_IPI_INT_IDX_SHFT                      52
-#define SH_IPI_INT_IDX_MASK                      0x0ff0000000000000UL
+#define SH_IPI_INT_IDX_MASK                      0x0ff0000000000000
 
 /*   SH_IPI_INT_SEND                                                    */
 /*   Description:  Send Interrupt Message to PI, This generates a puls  */
 #define SH_IPI_INT_SEND_SHFT                     63
-#define SH_IPI_INT_SEND_MASK                     0x8000000000000000UL
+#define SH_IPI_INT_SEND_MASK                     0x8000000000000000
 
 /* ==================================================================== */
 /*                     Register "SH_EVENT_OCCURRED"                     */
 /*                    SHub Interrupt Event Occurred                     */
 /* ==================================================================== */
-#define SH_EVENT_OCCURRED                        0x0000000110010000UL
-#define SH_EVENT_OCCURRED_ALIAS                  0x0000000110010008UL
+#define SH1_EVENT_OCCURRED                        0x0000000110010000
+#define SH1_EVENT_OCCURRED_ALIAS                  0x0000000110010008
+#define SH2_EVENT_OCCURRED                        0x0000000010010000
+#define SH2_EVENT_OCCURRED_ALIAS                  0x0000000010010008
 
 /* ==================================================================== */
 /*                     Register "SH_PI_CAM_CONTROL"                     */
 /*                      CRB CAM MMR Access Control                      */
 /* ==================================================================== */
-#ifndef __ASSEMBLY__
-#define SH_PI_CAM_CONTROL                        0x0000000120050300UL
-#else
-#define SH_PI_CAM_CONTROL                        0x0000000120050300
-#endif
+#define SH1_PI_CAM_CONTROL                        0x0000000120050300
 
 /* ==================================================================== */
 /*                        Register "SH_SHUB_ID"                         */
 /*                            SHub ID Number                            */
 /* ==================================================================== */
-#define SH_SHUB_ID                               0x0000000110060580UL
-#define SH_SHUB_ID_REVISION_SHFT                 28
-#define SH_SHUB_ID_REVISION_MASK                 0x00000000f0000000
-
-/* ==================================================================== */
-/*                         Register "SH_PTC_0"                          */
-/*       Puge Translation Cache Message Configuration Information       */
-/* ==================================================================== */
-#define SH_PTC_0                                 0x00000001101a0000UL
-#define SH_PTC_1                                 0x00000001101a0080UL
+#define SH1_SHUB_ID                               0x0000000110060580
+#define SH1_SHUB_ID_REVISION_SHFT                 28
+#define SH1_SHUB_ID_REVISION_MASK                 0x00000000f0000000
 
 /* ==================================================================== */
 /*                          Register "SH_RTC"                           */
 /*                           Real-time Clock                            */
 /* ==================================================================== */
-#define SH_RTC                                   0x00000001101c0000UL
-#define SH_RTC_MASK                              0x007fffffffffffffUL
-
-/* ==================================================================== */
-/*                 Register "SH_MEMORY_WRITE_STATUS_0|1"                */
-/*                    Memory Write Status for CPU 0 & 1                 */
-/* ==================================================================== */
-#define SH_MEMORY_WRITE_STATUS_0                 0x0000000120070000UL
-#define SH_MEMORY_WRITE_STATUS_1                 0x0000000120070080UL
+#define SH1_RTC                                   0x00000001101c0000
+#define SH2_RTC					  0x00000002101c0000
+#define SH_RTC_MASK                               0x007fffffffffffff
 
 /* ==================================================================== */
 /*                   Register "SH_PIO_WRITE_STATUS_0|1"                 */
 /*                      PIO Write Status for CPU 0 & 1                  */
 /* ==================================================================== */
-#ifndef __ASSEMBLY__
-#define SH_PIO_WRITE_STATUS_0                    0x0000000120070200UL
-#define SH_PIO_WRITE_STATUS_1                    0x0000000120070280UL
+#define SH1_PIO_WRITE_STATUS_0                    0x0000000120070200
+#define SH1_PIO_WRITE_STATUS_1                    0x0000000120070280
+#define SH2_PIO_WRITE_STATUS_0                    0x0000000020070200
+#define SH2_PIO_WRITE_STATUS_1                    0x0000000020070280
+#define SH2_PIO_WRITE_STATUS_2                    0x0000000020070300
+#define SH2_PIO_WRITE_STATUS_3                    0x0000000020070380
 
 /*   SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK                               */
 /*   Description:  Deadlock response detected                           */
-#define SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT 1
-#define SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK 0x0000000000000002
+#define SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT 1
+#define SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK 0x0000000000000002
 
 /*   SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT                          */
 /*   Description:  Count of currently pending PIO writes                */
-#define SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT 56
-#define SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK 0x3f00000000000000UL
-#else
-#define SH_PIO_WRITE_STATUS_0                    0x0000000120070200
-#define SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT 56
-#define SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT 1
-#endif
+#define SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_SHFT 56
+#define SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK 0x3f00000000000000
 
 /* ==================================================================== */
 /*                Register "SH_PIO_WRITE_STATUS_0_ALIAS"                */
 /* ==================================================================== */
-#ifndef __ASSEMBLY__
-#define SH_PIO_WRITE_STATUS_0_ALIAS              0x0000000120070208UL
-#else
-#define SH_PIO_WRITE_STATUS_0_ALIAS              0x0000000120070208
-#endif
+#define SH1_PIO_WRITE_STATUS_0_ALIAS              0x0000000120070208
+#define SH2_PIO_WRITE_STATUS_0_ALIAS              0x0000000020070208
 
 /* ==================================================================== */
 /*                     Register "SH_EVENT_OCCURRED"                     */
@@ -151,61 +130,85 @@
 #define SH_EVENT_OCCURRED_II_INT1_MASK           0x0000000040000000
 
 /* ==================================================================== */
-/*                         Register "SH_PTC_0"                          */
+/*                         LEDS                                         */
+/* ==================================================================== */
+#define SH1_REAL_JUNK_BUS_LED0			 0x7fed00000UL
+#define SH1_REAL_JUNK_BUS_LED1			 0x7fed10000UL
+#define SH1_REAL_JUNK_BUS_LED2			 0x7fed20000UL
+#define SH1_REAL_JUNK_BUS_LED3			 0x7fed30000UL
+
+#define SH2_REAL_JUNK_BUS_LED0			 0xf0000000UL
+#define SH2_REAL_JUNK_BUS_LED1			 0xf0010000UL
+#define SH2_REAL_JUNK_BUS_LED2			 0xf0020000UL
+#define SH2_REAL_JUNK_BUS_LED3			 0xf0030000UL
+
+/* ==================================================================== */
+/*                         Register "SH1_PTC_0"                         */
 /*       Puge Translation Cache Message Configuration Information       */
 /* ==================================================================== */
-#define SH_PTC_0                                 0x00000001101a0000UL
-#define SH_PTC_0_MASK                            0x80000000fffffffd
-#define SH_PTC_0_INIT                            0x0000000000000000
+#define SH1_PTC_0                                 0x00000001101a0000
 
-/*   SH_PTC_0_A                                                         */
+/*   SH1_PTC_0_A                                                        */
 /*   Description:  Type                                                 */
-#define SH_PTC_0_A_SHFT                          0
-#define SH_PTC_0_A_MASK                          0x0000000000000001
+#define SH1_PTC_0_A_SHFT                          0
 
-/*   SH_PTC_0_PS                                                        */
+/*   SH1_PTC_0_PS                                                       */
 /*   Description:  Page Size                                            */
-#define SH_PTC_0_PS_SHFT                         2
-#define SH_PTC_0_PS_MASK                         0x00000000000000fc
+#define SH1_PTC_0_PS_SHFT                         2
 
-/*   SH_PTC_0_RID                                                       */
+/*   SH1_PTC_0_RID                                                      */
 /*   Description:  Region ID                                            */
-#define SH_PTC_0_RID_SHFT                        8
-#define SH_PTC_0_RID_MASK                        0x00000000ffffff00
+#define SH1_PTC_0_RID_SHFT                        8
 
-/*   SH_PTC_0_START                                                     */
+/*   SH1_PTC_0_START                                                    */
 /*   Description:  Start                                                */
-#define SH_PTC_0_START_SHFT                      63
-#define SH_PTC_0_START_MASK                      0x8000000000000000
+#define SH1_PTC_0_START_SHFT                      63
 
 /* ==================================================================== */
-/*                         Register "SH_PTC_1"                          */
+/*                         Register "SH1_PTC_1"                         */
 /*       Puge Translation Cache Message Configuration Information       */
 /* ==================================================================== */
-#define SH_PTC_1                                 0x00000001101a0080UL
-#define SH_PTC_1_MASK                            0x9ffffffffffff000
-#define SH_PTC_1_INIT                            0x0000000000000000
-
-/*   SH_PTC_1_VPN                                                       */
-/*   Description:  Virtual page number                                  */
-#define SH_PTC_1_VPN_SHFT                        12
-#define SH_PTC_1_VPN_MASK                        0x1ffffffffffff000
+#define SH1_PTC_1                                 0x00000001101a0080
 
-/*   SH_PTC_1_START                                                     */
+/*   SH1_PTC_1_START                                                    */
 /*   Description:  PTC_1 Start                                          */
-#define SH_PTC_1_START_SHFT                      63
-#define SH_PTC_1_START_MASK                      0x8000000000000000
+#define SH1_PTC_1_START_SHFT                      63
+
+
+/* ==================================================================== */
+/*                         Register "SH2_PTC"                           */
+/*       Puge Translation Cache Message Configuration Information       */
+/* ==================================================================== */
+#define SH2_PTC                                   0x0000000170000000
+
+/*   SH2_PTC_A                                                          */
+/*   Description:  Type                                                 */
+#define SH2_PTC_A_SHFT                            0
+
+/*   SH2_PTC_PS                                                         */
+/*   Description:  Page Size                                            */
+#define SH2_PTC_PS_SHFT                           2
+
+/*   SH2_PTC_RID                                                      */
+/*   Description:  Region ID                                            */
+#define SH2_PTC_RID_SHFT                          4
+
+/*   SH2_PTC_START                                                      */
+/*   Description:  Start                                                */
+#define SH2_PTC_START_SHFT                        63
 
-/*
- * Register definitions
- */
+/*   SH2_PTC_ADDR_RID                                                   */
+/*   Description:  Region ID                                            */
+#define SH2_PTC_ADDR_SHFT                         4
+#define SH2_PTC_ADDR_MASK                         0x1ffffffffffff000
 
 /* ==================================================================== */
 /*                    Register "SH_RTC1_INT_CONFIG"                     */
 /*                SHub RTC 1 Interrupt Config Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC1_INT_CONFIG                       0x0000000110001480
+#define SH1_RTC1_INT_CONFIG                      0x0000000110001480
+#define SH2_RTC1_INT_CONFIG                      0x0000000010001480
 #define SH_RTC1_INT_CONFIG_MASK                  0x0ff3ffffffefffff
 #define SH_RTC1_INT_CONFIG_INIT                  0x0000000000000000
 
@@ -239,7 +242,8 @@
 /*                SHub RTC 1 Interrupt Enable Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC1_INT_ENABLE                       0x0000000110001500
+#define SH1_RTC1_INT_ENABLE                      0x0000000110001500
+#define SH2_RTC1_INT_ENABLE                      0x0000000010001500
 #define SH_RTC1_INT_ENABLE_MASK                  0x0000000000000001
 #define SH_RTC1_INT_ENABLE_INIT                  0x0000000000000000
 
@@ -253,7 +257,8 @@
 /*                SHub RTC 2 Interrupt Config Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC2_INT_CONFIG                       0x0000000110001580
+#define SH1_RTC2_INT_CONFIG                      0x0000000110001580
+#define SH2_RTC2_INT_CONFIG                      0x0000000010001580
 #define SH_RTC2_INT_CONFIG_MASK                  0x0ff3ffffffefffff
 #define SH_RTC2_INT_CONFIG_INIT                  0x0000000000000000
 
@@ -287,7 +292,8 @@
 /*                SHub RTC 2 Interrupt Enable Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC2_INT_ENABLE                       0x0000000110001600
+#define SH1_RTC2_INT_ENABLE                      0x0000000110001600
+#define SH2_RTC2_INT_ENABLE                      0x0000000010001600
 #define SH_RTC2_INT_ENABLE_MASK                  0x0000000000000001
 #define SH_RTC2_INT_ENABLE_INIT                  0x0000000000000000
 
@@ -301,7 +307,8 @@
 /*                SHub RTC 3 Interrupt Config Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC3_INT_CONFIG                       0x0000000110001680
+#define SH1_RTC3_INT_CONFIG                      0x0000000110001680
+#define SH2_RTC3_INT_CONFIG                      0x0000000010001680
 #define SH_RTC3_INT_CONFIG_MASK                  0x0ff3ffffffefffff
 #define SH_RTC3_INT_CONFIG_INIT                  0x0000000000000000
 
@@ -335,7 +342,8 @@
 /*                SHub RTC 3 Interrupt Enable Registers                 */
 /* ==================================================================== */
 
-#define SH_RTC3_INT_ENABLE                       0x0000000110001700
+#define SH1_RTC3_INT_ENABLE                      0x0000000110001700
+#define SH2_RTC3_INT_ENABLE                      0x0000000010001700
 #define SH_RTC3_INT_ENABLE_MASK                  0x0000000000000001
 #define SH_RTC3_INT_ENABLE_INIT                  0x0000000000000000
 
@@ -364,7 +372,8 @@
 /*                  RTC Compare Value for Processor B                   */
 /* ==================================================================== */
 
-#define SH_INT_CMPB                              0x00000001101b0080
+#define SH1_INT_CMPB                             0x00000001101b0080
+#define SH2_INT_CMPB                             0x00000000101b0080
 #define SH_INT_CMPB_MASK                         0x007fffffffffffff
 #define SH_INT_CMPB_INIT                         0x0000000000000000
 
@@ -378,7 +387,8 @@
 /*                  RTC Compare Value for Processor C                   */
 /* ==================================================================== */
 
-#define SH_INT_CMPC                              0x00000001101b0100
+#define SH1_INT_CMPC                             0x00000001101b0100
+#define SH2_INT_CMPC                             0x00000000101b0100
 #define SH_INT_CMPC_MASK                         0x007fffffffffffff
 #define SH_INT_CMPC_INIT                         0x0000000000000000
 
@@ -392,7 +402,8 @@
 /*                  RTC Compare Value for Processor D                   */
 /* ==================================================================== */
 
-#define SH_INT_CMPD                              0x00000001101b0180
+#define SH1_INT_CMPD                             0x00000001101b0180
+#define SH2_INT_CMPD                             0x00000000101b0180
 #define SH_INT_CMPD_MASK                         0x007fffffffffffff
 #define SH_INT_CMPD_INIT                         0x0000000000000000
 
@@ -400,5 +411,31 @@
 /*   Description:  Real Time Clock Compare                              */
 #define SH_INT_CMPD_REAL_TIME_CMPD_SHFT          0
 #define SH_INT_CMPD_REAL_TIME_CMPD_MASK          0x007fffffffffffff
+
+
+/* ==================================================================== */
+/* Some MMRs are functionally identical (or close enough) on both SHUB1 */
+/* and SHUB2 that it makes sense to define a geberic name for the MMR.  */
+/* It is acceptible to use (for example) SH_IPI_INT to reference the    */
+/* the IPI MMR. The value of SH_IPI_INT is determined at runtime based  */
+/* on the type of the SHUB. Do not use these #defines in performance    */
+/* critical code  or loops - there is a small performance penalty.      */
+/* ==================================================================== */
+#define shubmmr(a,b) 		(is_shub2() ? a##2_##b : a##1_##b)
+
+#define SH_REAL_JUNK_BUS_LED0	shubmmr(SH, REAL_JUNK_BUS_LED0)
+#define SH_IPI_INT		shubmmr(SH, IPI_INT)
+#define SH_EVENT_OCCURRED	shubmmr(SH, EVENT_OCCURRED)
+#define SH_EVENT_OCCURRED_ALIAS	shubmmr(SH, EVENT_OCCURRED_ALIAS)
+#define SH_RTC			shubmmr(SH, RTC)
+#define SH_RTC1_INT_CONFIG	shubmmr(SH, RTC1_INT_CONFIG)
+#define SH_RTC1_INT_ENABLE	shubmmr(SH, RTC1_INT_ENABLE)
+#define SH_RTC2_INT_CONFIG	shubmmr(SH, RTC2_INT_CONFIG)
+#define SH_RTC2_INT_ENABLE	shubmmr(SH, RTC2_INT_ENABLE)
+#define SH_RTC3_INT_CONFIG	shubmmr(SH, RTC3_INT_CONFIG)
+#define SH_RTC3_INT_ENABLE	shubmmr(SH, RTC3_INT_ENABLE)
+#define SH_INT_CMPB		shubmmr(SH, INT_CMPB)
+#define SH_INT_CMPC		shubmmr(SH, INT_CMPC)
+#define SH_INT_CMPD		shubmmr(SH, INT_CMPD)
 
 #endif /* _ASM_IA64_SN_SHUB_MMR_H */
diff -Nru a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
--- a/include/asm-ia64/sn/sn_cpuid.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/sn_cpuid.h	2005-01-05 18:28:29 -08:00
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/smp.h>
+#include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
 #include <asm/intrinsics.h>
 
@@ -86,11 +87,9 @@
 #endif
 
 
-#define get_node_number(addr)			(((unsigned long)(addr)>>38) & 0x7ff)
+#define get_node_number(addr)			NASID_GET(addr)
 
 /*
- * NOTE: id & eid refer to Intel's definitions of the LID register
- * 
  * NOTE: on non-MP systems, only cpuid 0 exists
  */
 
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/sn/sn_sal.h	2005-01-05 18:28:29 -08:00
@@ -32,9 +32,10 @@
 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL		   0x02000010
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
-#define  SN_SAL_GET_SAPIC_INFO                     0x02009999	//ZZZZ fix
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
 #define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
+#define  SN_SAL_GET_HUB_INFO                       0x0200001c
+#define  SN_SAL_GET_SAPIC_INFO                     0x0200001d
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
 #define  SN_SAL_CONSOLE_GETC                       0x02000022
 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
@@ -847,6 +848,14 @@
 
 /*
  * Returns the nasid, subnode & slice corresponding to a SAPIC ID
+ *
+ *  In:
+ *	arg0 - SN_SAL_GET_SAPIC_INFO
+ *	arg1 - sapicid (lid >> 16) 
+ *  Out:
+ *	v0 - nasid
+ *	v1 - subnode
+ *	v2 - slice
  */
 static inline u64
 ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice)
@@ -859,7 +868,7 @@
 	ret_stuff.v2 = 0;
 	SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SAPIC_INFO, sapicid, 0, 0, 0, 0, 0, 0);
 
-/***** BEGIN HACK - temp til new proms available ********/
+/***** BEGIN HACK - temp til old proms no longer supported ********/
 	if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
 		if (nasid) *nasid = sapicid & 0xfff;
 		if (subnode) *subnode = (sapicid >> 13) & 1;
@@ -876,6 +885,46 @@
 	if (slice) *slice = (int) ret_stuff.v2;
 	return 0;
 }
+ 
+/*
+ * Returns information about the HUB/SHUB.
+ *  In:
+ *	arg0 - SN_SAL_GET_HUB_INFO
+ * 	arg1 - 0 (other values reserved for future use)
+ *  Out:
+ *	v0 - shub type (0=shub1, 1=shub2)
+ *	v1 - masid mask (ex., 0x7ff for 11 bit nasid)
+ *	v2 - bit position of low nasid bit
+ */
+static inline u64
+ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
+{
+	struct ia64_sal_retval ret_stuff;
+
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+	ret_stuff.v1 = 0;
+	ret_stuff.v2 = 0;
+	SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_HUB_INFO, fc, 0, 0, 0, 0, 0, 0);
+
+/***** BEGIN HACK - temp til old proms no longer supported ********/
+	if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
+		if (arg1) *arg1 = 0;
+		if (arg2) *arg2 = 0x7ff;
+		if (arg3) *arg3 = 38;
+		return 0;
+	}
+/***** END HACK *******/
+
+	if (ret_stuff.status < 0)
+		return ret_stuff.status;
+
+	if (arg1) *arg1 = ret_stuff.v0;
+	if (arg2) *arg2 = ret_stuff.v1;
+	if (arg3) *arg3 = ret_stuff.v2;
+	return 0;
+}
+ 
 /*
  * This is the access point to the Altix PROM hardware performance
  * and status monitoring interface. For info on using this, see
diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
--- a/include/asm-ia64/thread_info.h	2005-01-05 18:28:29 -08:00
+++ b/include/asm-ia64/thread_info.h	2005-01-05 18:28:29 -08:00
@@ -27,6 +27,13 @@
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__s32 preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
 	struct restart_block restart_block;
+	struct {
+		int signo;
+		int code;
+		void __user *addr;
+		unsigned long start_time;
+		pid_t pid;
+	} sigdelayed;			/* Saved information for TIF_SIGDELAYED */
 };
 
 #define THREAD_SIZE			KERNEL_STACK_SIZE
@@ -66,18 +73,21 @@
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SYSCALL_TRACE	3	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
+#define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
-#define TIF_WORK_MASK		0x7	/* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE */
-#define TIF_ALLWORK_MASK	0x1f	/* bits 0..4 are "work to do on user-return" bits */
-
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
-#define _TIF_USEDFPU		(1 << TIF_USEDFPU)
+#define _TIF_SIGDELAYED	(1 << TIF_SIGDELAYED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+
+/* "work to do on user-return" bits */
+#define TIF_ALLWORK_MASK	(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED)
+/* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
+#define TIF_WORK_MASK		(TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
 
 #endif /* _ASM_IA64_THREAD_INFO_H */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2005-01-05 18:28:29 -08:00
+++ b/include/linux/sched.h	2005-01-05 18:28:29 -08:00
@@ -762,6 +762,7 @@
 extern int task_nice(const task_t *p);
 extern int task_curr(const task_t *p);
 extern int idle_cpu(int cpu);
+extern task_t *idle_task(int cpu);
 
 void yield(void);
 
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	2005-01-05 18:28:29 -08:00
+++ b/kernel/sched.c	2005-01-05 18:28:29 -08:00
@@ -3068,6 +3068,15 @@
 EXPORT_SYMBOL_GPL(idle_cpu);
 
 /**
+ * idle_task - return the idle task for a given cpu.
+ * @cpu: the processor in question.
+ */
+task_t *idle_task(int cpu)
+{
+	return cpu_rq(cpu)->idle;
+}
+
+/**
  * find_process_by_pid - find a process with a matching PID value.
  * @pid: the pid in question.
  */
