aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel')
-rw-r--r--arch/ia64/sn/kernel/Makefile2
-rw-r--r--arch/ia64/sn/kernel/bte.c17
-rw-r--r--arch/ia64/sn/kernel/io_init.c9
-rw-r--r--arch/ia64/sn/kernel/irq.c21
-rw-r--r--arch/ia64/sn/kernel/klconflib.c29
-rw-r--r--arch/ia64/sn/kernel/setup.c19
-rw-r--r--arch/ia64/sn/kernel/sn2/Makefile2
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c196
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c19
9 files changed, 139 insertions, 175 deletions
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 4351c4ff9845..3e9b4eea7418 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -7,6 +7,8 @@
7# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. 7# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved.
8# 8#
9 9
10CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
11
10obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ 12obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
11 huberror.o io_init.o iomv.o klconflib.o sn2/ 13 huberror.o io_init.o iomv.o klconflib.o sn2/
12obj-$(CONFIG_IA64_GENERIC) += machvec.o 14obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index dd73c0cb754b..1f11db470d90 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9#include <linux/config.h> 9#include <linux/config.h>
@@ -186,18 +186,13 @@ retry_bteop:
186 186
187 /* Initialize the notification to a known value. */ 187 /* Initialize the notification to a known value. */
188 *bte->most_rcnt_na = BTE_WORD_BUSY; 188 *bte->most_rcnt_na = BTE_WORD_BUSY;
189 notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)); 189 notif_phys_addr = (u64)bte->most_rcnt_na;
190 190
191 if (is_shub2()) {
192 src = SH2_TIO_PHYS_TO_DMA(src);
193 dest = SH2_TIO_PHYS_TO_DMA(dest);
194 notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr);
195 }
196 /* Set the source and destination registers */ 191 /* Set the source and destination registers */
197 BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); 192 BTE_PRINTKV(("IBSA = 0x%lx)\n", src));
198 BTE_SRC_STORE(bte, TO_PHYS(src)); 193 BTE_SRC_STORE(bte, src);
199 BTE_PRINTKV(("IBDA = 0x%lx)\n", (TO_PHYS(dest)))); 194 BTE_PRINTKV(("IBDA = 0x%lx)\n", dest));
200 BTE_DEST_STORE(bte, TO_PHYS(dest)); 195 BTE_DEST_STORE(bte, dest);
201 196
202 /* Set the notification register */ 197 /* Set the notification register */
203 BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); 198 BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr));
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index a4c78152b336..d7e4d79e16a8 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -208,7 +208,7 @@ static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
208 * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 208 * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
209 * each node in the system. 209 * each node in the system.
210 */ 210 */
211static void sn_fixup_ionodes(void) 211static void __init sn_fixup_ionodes(void)
212{ 212{
213 struct sn_flush_device_kernel *sn_flush_device_kernel; 213 struct sn_flush_device_kernel *sn_flush_device_kernel;
214 struct sn_flush_device_kernel *dev_entry; 214 struct sn_flush_device_kernel *dev_entry;
@@ -467,6 +467,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
467 pcidev_info->pdi_sn_irq_info = NULL; 467 pcidev_info->pdi_sn_irq_info = NULL;
468 kfree(sn_irq_info); 468 kfree(sn_irq_info);
469 } 469 }
470
471 /*
472 * MSI currently not supported on altix. Remove this when
473 * the MSI abstraction patches are integrated into the kernel
474 * (sometime after 2.6.16 releases)
475 */
476 dev->no_msi = 1;
470} 477}
471 478
472/* 479/*
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index ec37084bdc17..74d87d903d5d 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,11 +5,12 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. 8 * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
9 */ 9 */
10 10
11#include <linux/irq.h> 11#include <linux/irq.h>
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/init.h>
13#include <asm/sn/addrs.h> 14#include <asm/sn/addrs.h>
14#include <asm/sn/arch.h> 15#include <asm/sn/arch.h>
15#include <asm/sn/intr.h> 16#include <asm/sn/intr.h>
@@ -76,17 +77,15 @@ static void sn_enable_irq(unsigned int irq)
76 77
77static void sn_ack_irq(unsigned int irq) 78static void sn_ack_irq(unsigned int irq)
78{ 79{
79 u64 event_occurred, mask = 0; 80 u64 event_occurred, mask;
80 81
81 irq = irq & 0xff; 82 irq = irq & 0xff;
82 event_occurred = 83 event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
83 HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
84 mask = event_occurred & SH_ALL_INT_MASK; 84 mask = event_occurred & SH_ALL_INT_MASK;
85 HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), 85 HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
86 mask);
87 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); 86 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
88 87
89 move_irq(irq); 88 move_native_irq(irq);
90} 89}
91 90
92static void sn_end_irq(unsigned int irq) 91static void sn_end_irq(unsigned int irq)
@@ -219,9 +218,8 @@ static void register_intr_pda(struct sn_irq_info *sn_irq_info)
219 pdacpu(cpu)->sn_last_irq = irq; 218 pdacpu(cpu)->sn_last_irq = irq;
220 } 219 }
221 220
222 if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { 221 if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq)
223 pdacpu(cpu)->sn_first_irq = irq; 222 pdacpu(cpu)->sn_first_irq = irq;
224 }
225} 223}
226 224
227static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) 225static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
@@ -289,7 +287,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
289 list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); 287 list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
290 spin_unlock(&sn_irq_info_lock); 288 spin_unlock(&sn_irq_info_lock);
291 289
292 (void)register_intr_pda(sn_irq_info); 290 register_intr_pda(sn_irq_info);
293} 291}
294 292
295void sn_irq_unfixup(struct pci_dev *pci_dev) 293void sn_irq_unfixup(struct pci_dev *pci_dev)
@@ -419,7 +417,7 @@ void sn_lb_int_war_check(void)
419 rcu_read_unlock(); 417 rcu_read_unlock();
420} 418}
421 419
422void sn_irq_lh_init(void) 420void __init sn_irq_lh_init(void)
423{ 421{
424 int i; 422 int i;
425 423
@@ -434,5 +432,4 @@ void sn_irq_lh_init(void)
434 432
435 INIT_LIST_HEAD(sn_irq_lh[i]); 433 INIT_LIST_HEAD(sn_irq_lh[i]);
436 } 434 }
437
438} 435}
diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c
index 0f11a3299cd2..87682b48ef83 100644
--- a/arch/ia64/sn/kernel/klconflib.c
+++ b/arch/ia64/sn/kernel/klconflib.c
@@ -78,31 +78,30 @@ format_module_id(char *buffer, moduleid_t m, int fmt)
78 position = MODULE_GET_BPOS(m); 78 position = MODULE_GET_BPOS(m);
79 79
80 if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { 80 if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) {
81 /* Brief module number format, eg. 002c15 */ 81 /* Brief module number format, eg. 002c15 */
82 82
83 /* Decompress the rack number */ 83 /* Decompress the rack number */
84 *buffer++ = '0' + RACK_GET_CLASS(rack); 84 *buffer++ = '0' + RACK_GET_CLASS(rack);
85 *buffer++ = '0' + RACK_GET_GROUP(rack); 85 *buffer++ = '0' + RACK_GET_GROUP(rack);
86 *buffer++ = '0' + RACK_GET_NUM(rack); 86 *buffer++ = '0' + RACK_GET_NUM(rack);
87 87
88 /* Add the brick type */ 88 /* Add the brick type */
89 *buffer++ = brickchar; 89 *buffer++ = brickchar;
90 } 90 }
91 else if (fmt == MODULE_FORMAT_LONG) { 91 else if (fmt == MODULE_FORMAT_LONG) {
92 /* Fuller hwgraph format, eg. rack/002/bay/15 */ 92 /* Fuller hwgraph format, eg. rack/002/bay/15 */
93 93
94 strcpy(buffer, "rack" "/"); buffer += strlen(buffer); 94 strcpy(buffer, "rack" "/"); buffer += strlen(buffer);
95 95
96 *buffer++ = '0' + RACK_GET_CLASS(rack); 96 *buffer++ = '0' + RACK_GET_CLASS(rack);
97 *buffer++ = '0' + RACK_GET_GROUP(rack); 97 *buffer++ = '0' + RACK_GET_GROUP(rack);
98 *buffer++ = '0' + RACK_GET_NUM(rack); 98 *buffer++ = '0' + RACK_GET_NUM(rack);
99 99
100 strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); 100 strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer);
101 } 101 }
102 102
103 /* Add the bay position, using at least two digits */ 103 /* Add the bay position, using at least two digits */
104 if (position < 10) 104 if (position < 10)
105 *buffer++ = '0'; 105 *buffer++ = '0';
106 sprintf(buffer, "%d", position); 106 sprintf(buffer, "%d", position);
107
108} 107}
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index e510dce9971f..ee36bff93c30 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -209,7 +209,7 @@ void __init early_sn_setup(void)
209} 209}
210 210
211extern int platform_intr_list[]; 211extern int platform_intr_list[];
212static int __initdata shub_1_1_found = 0; 212static int __initdata shub_1_1_found;
213 213
214/* 214/*
215 * sn_check_for_wars 215 * sn_check_for_wars
@@ -578,13 +578,17 @@ void __init sn_cpu_init(void)
578 sn_prom_type = 2; 578 sn_prom_type = 2;
579 else 579 else
580 sn_prom_type = 1; 580 sn_prom_type = 1;
581 printk("Running on medusa with %s PROM\n", (sn_prom_type == 1) ? "real" : "fake"); 581 printk(KERN_INFO "Running on medusa with %s PROM\n",
582 (sn_prom_type == 1) ? "real" : "fake");
582 } 583 }
583 584
584 memset(pda, 0, sizeof(pda)); 585 memset(pda, 0, sizeof(pda));
585 if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, 586 if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
586 &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, 587 &sn_hub_info->nasid_bitmask,
587 &sn_coherency_id, &sn_region_size)) 588 &sn_hub_info->nasid_shift,
589 &sn_system_size, &sn_sharing_domain_size,
590 &sn_partition_id, &sn_coherency_id,
591 &sn_region_size))
588 BUG(); 592 BUG();
589 sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; 593 sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
590 594
@@ -716,7 +720,8 @@ void __init build_cnode_tables(void)
716 for_each_online_node(node) { 720 for_each_online_node(node) {
717 kl_config_hdr_t *klgraph_header; 721 kl_config_hdr_t *klgraph_header;
718 nasid = cnodeid_to_nasid(node); 722 nasid = cnodeid_to_nasid(node);
719 if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL) 723 klgraph_header = ia64_sn_get_klconfig_addr(nasid);
724 if (klgraph_header == NULL)
720 BUG(); 725 BUG();
721 brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info); 726 brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
722 while (brd) { 727 while (brd) {
@@ -734,7 +739,7 @@ nasid_slice_to_cpuid(int nasid, int slice)
734{ 739{
735 long cpu; 740 long cpu;
736 741
737 for (cpu=0; cpu < NR_CPUS; cpu++) 742 for (cpu = 0; cpu < NR_CPUS; cpu++)
738 if (cpuid_to_nasid(cpu) == nasid && 743 if (cpuid_to_nasid(cpu) == nasid &&
739 cpuid_to_slice(cpu) == slice) 744 cpuid_to_slice(cpu) == slice)
740 return cpu; 745 return cpu;
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 170bde4549da..99e177693234 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -9,5 +9,7 @@
9# sn2 specific kernel files 9# sn2 specific kernel files
10# 10#
11 11
12CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
13
12obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ 14obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
13 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o 15 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 471bbaa65d1b..f153a4c35c70 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. 8 * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved.
9 */ 9 */
10 10
11#include <linux/init.h> 11#include <linux/init.h>
@@ -46,104 +46,28 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats);
46 46
47static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); 47static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
48 48
49void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, 49void sn2_ptc_deadlock_recovery(short *, short, short, int, volatile unsigned long *, unsigned long,
50 volatile unsigned long *, unsigned long data1); 50 volatile unsigned long *, unsigned long);
51 51
52#ifdef DEBUG_PTC
53/* 52/*
54 * ptctest: 53 * Note: some is the following is captured here to make degugging easier
55 * 54 * (the macros make more sense if you see the debug patch - not posted)
56 * xyz - 3 digit hex number:
57 * x - Force PTC purges to use shub:
58 * 0 - no force
59 * 1 - force
60 * y - interupt enable
61 * 0 - disable interrupts
62 * 1 - leave interuupts enabled
63 * z - type of lock:
64 * 0 - global lock
65 * 1 - node local lock
66 * 2 - no lock
67 *
68 * Note: on shub1, only ptctest == 0 is supported. Don't try other values!
69 */ 55 */
70
71static unsigned int sn2_ptctest = 0;
72
73static int __init ptc_test(char *str)
74{
75 get_option(&str, &sn2_ptctest);
76 return 1;
77}
78__setup("ptctest=", ptc_test);
79
80static inline int ptc_lock(unsigned long *flagp)
81{
82 unsigned long opt = sn2_ptctest & 255;
83
84 switch (opt) {
85 case 0x00:
86 spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
87 break;
88 case 0x01:
89 spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp);
90 break;
91 case 0x02:
92 local_irq_save(*flagp);
93 break;
94 case 0x10:
95 spin_lock(&sn2_global_ptc_lock);
96 break;
97 case 0x11:
98 spin_lock(&sn_nodepda->ptc_lock);
99 break;
100 case 0x12:
101 break;
102 default:
103 BUG();
104 }
105 return opt;
106}
107
108static inline void ptc_unlock(unsigned long flags, int opt)
109{
110 switch (opt) {
111 case 0x00:
112 spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
113 break;
114 case 0x01:
115 spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags);
116 break;
117 case 0x02:
118 local_irq_restore(flags);
119 break;
120 case 0x10:
121 spin_unlock(&sn2_global_ptc_lock);
122 break;
123 case 0x11:
124 spin_unlock(&sn_nodepda->ptc_lock);
125 break;
126 case 0x12:
127 break;
128 default:
129 BUG();
130 }
131}
132#else
133
134#define sn2_ptctest 0 56#define sn2_ptctest 0
57#define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0)
58#define max_active_pio(sh1) ((sh1) ? 32 : 7)
59#define reset_max_active_on_deadlock() 1
60#define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock)
135 61
136static inline int ptc_lock(unsigned long *flagp) 62static inline void ptc_lock(int sh1, unsigned long *flagp)
137{ 63{
138 spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); 64 spin_lock_irqsave(PTC_LOCK(sh1), *flagp);
139 return 0;
140} 65}
141 66
142static inline void ptc_unlock(unsigned long flags, int opt) 67static inline void ptc_unlock(int sh1, unsigned long flags)
143{ 68{
144 spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); 69 spin_unlock_irqrestore(PTC_LOCK(sh1), flags);
145} 70}
146#endif
147 71
148struct ptc_stats { 72struct ptc_stats {
149 unsigned long ptc_l; 73 unsigned long ptc_l;
@@ -151,27 +75,30 @@ struct ptc_stats {
151 unsigned long shub_ptc_flushes; 75 unsigned long shub_ptc_flushes;
152 unsigned long nodes_flushed; 76 unsigned long nodes_flushed;
153 unsigned long deadlocks; 77 unsigned long deadlocks;
78 unsigned long deadlocks2;
154 unsigned long lock_itc_clocks; 79 unsigned long lock_itc_clocks;
155 unsigned long shub_itc_clocks; 80 unsigned long shub_itc_clocks;
156 unsigned long shub_itc_clocks_max; 81 unsigned long shub_itc_clocks_max;
82 unsigned long shub_ptc_flushes_not_my_mm;
157}; 83};
158 84
159static inline unsigned long wait_piowc(void) 85static inline unsigned long wait_piowc(void)
160{ 86{
161 volatile unsigned long *piows, zeroval; 87 volatile unsigned long *piows;
162 unsigned long ws; 88 unsigned long zeroval, ws;
163 89
164 piows = pda->pio_write_status_addr; 90 piows = pda->pio_write_status_addr;
165 zeroval = pda->pio_write_status_val; 91 zeroval = pda->pio_write_status_val;
166 do { 92 do {
167 cpu_relax(); 93 cpu_relax();
168 } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); 94 } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval);
169 return ws; 95 return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
170} 96}
171 97
172void sn_tlb_migrate_finish(struct mm_struct *mm) 98void sn_tlb_migrate_finish(struct mm_struct *mm)
173{ 99{
174 if (mm == current->mm) 100 /* flush_tlb_mm is inefficient if more than 1 users of mm */
101 if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1)
175 flush_tlb_mm(mm); 102 flush_tlb_mm(mm);
176} 103}
177 104
@@ -201,12 +128,14 @@ void
201sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, 128sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
202 unsigned long end, unsigned long nbits) 129 unsigned long end, unsigned long nbits)
203{ 130{
204 int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; 131 int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid;
205 int mymm = (mm == current->active_mm && current->mm); 132 int mymm = (mm == current->active_mm && mm == current->mm);
133 int use_cpu_ptcga;
206 volatile unsigned long *ptc0, *ptc1; 134 volatile unsigned long *ptc0, *ptc1;
207 unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; 135 unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
208 short nasids[MAX_NUMNODES], nix; 136 short nasids[MAX_NUMNODES], nix;
209 nodemask_t nodes_flushed; 137 nodemask_t nodes_flushed;
138 int active, max_active, deadlock;
210 139
211 nodes_clear(nodes_flushed); 140 nodes_clear(nodes_flushed);
212 i = 0; 141 i = 0;
@@ -267,41 +196,56 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
267 196
268 197
269 mynasid = get_nasid(); 198 mynasid = get_nasid();
199 use_cpu_ptcga = local_node_uses_ptc_ga(shub1);
200 max_active = max_active_pio(shub1);
270 201
271 itc = ia64_get_itc(); 202 itc = ia64_get_itc();
272 opt = ptc_lock(&flags); 203 ptc_lock(shub1, &flags);
273 itc2 = ia64_get_itc(); 204 itc2 = ia64_get_itc();
205
274 __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; 206 __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc;
275 __get_cpu_var(ptcstats).shub_ptc_flushes++; 207 __get_cpu_var(ptcstats).shub_ptc_flushes++;
276 __get_cpu_var(ptcstats).nodes_flushed += nix; 208 __get_cpu_var(ptcstats).nodes_flushed += nix;
209 if (!mymm)
210 __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++;
277 211
212 if (use_cpu_ptcga && !mymm) {
213 old_rr = ia64_get_rr(start);
214 ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8));
215 ia64_srlz_d();
216 }
217
218 wait_piowc();
278 do { 219 do {
279 if (shub1) 220 if (shub1)
280 data1 = start | (1UL << SH1_PTC_1_START_SHFT); 221 data1 = start | (1UL << SH1_PTC_1_START_SHFT);
281 else 222 else
282 data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); 223 data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
283 for (i = 0; i < nix; i++) { 224 deadlock = 0;
225 active = 0;
226 for (ibegin = 0, i = 0; i < nix; i++) {
284 nasid = nasids[i]; 227 nasid = nasids[i];
285 if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) { 228 if (use_cpu_ptcga && unlikely(nasid == mynasid)) {
286 ia64_ptcga(start, nbits << 2); 229 ia64_ptcga(start, nbits << 2);
287 ia64_srlz_i(); 230 ia64_srlz_i();
288 } else { 231 } else {
289 ptc0 = CHANGE_NASID(nasid, ptc0); 232 ptc0 = CHANGE_NASID(nasid, ptc0);
290 if (ptc1) 233 if (ptc1)
291 ptc1 = CHANGE_NASID(nasid, ptc1); 234 ptc1 = CHANGE_NASID(nasid, ptc1);
292 pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, 235 pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
293 data1); 236 active++;
294 flushed = 1; 237 }
238 if (active >= max_active || i == (nix - 1)) {
239 if ((deadlock = wait_piowc())) {
240 sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
241 if (reset_max_active_on_deadlock())
242 max_active = 1;
243 }
244 active = 0;
245 ibegin = i + 1;
295 } 246 }
296 } 247 }
297 if (flushed
298 && (wait_piowc() &
299 (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) {
300 sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1);
301 }
302
303 start += (1UL << nbits); 248 start += (1UL << nbits);
304
305 } while (start < end); 249 } while (start < end);
306 250
307 itc2 = ia64_get_itc() - itc2; 251 itc2 = ia64_get_itc() - itc2;
@@ -309,7 +253,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
309 if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) 253 if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
310 __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; 254 __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;
311 255
312 ptc_unlock(flags, opt); 256 if (old_rr) {
257 ia64_set_rr(start, old_rr);
258 ia64_srlz_d();
259 }
260
261 ptc_unlock(shub1, flags);
313 262
314 preempt_enable(); 263 preempt_enable();
315} 264}
@@ -321,27 +270,30 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
321 * TLB flush transaction. The recovery sequence is somewhat tricky & is 270 * TLB flush transaction. The recovery sequence is somewhat tricky & is
322 * coded in assembly language. 271 * coded in assembly language.
323 */ 272 */
324void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, 273void sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, volatile unsigned long *ptc0, unsigned long data0,
325 volatile unsigned long *ptc1, unsigned long data1) 274 volatile unsigned long *ptc1, unsigned long data1)
326{ 275{
327 extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, 276 extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
328 volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); 277 volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long);
329 short nasid, i; 278 short nasid, i;
330 unsigned long *piows, zeroval; 279 unsigned long *piows, zeroval, n;
331 280
332 __get_cpu_var(ptcstats).deadlocks++; 281 __get_cpu_var(ptcstats).deadlocks++;
333 282
334 piows = (unsigned long *) pda->pio_write_status_addr; 283 piows = (unsigned long *) pda->pio_write_status_addr;
335 zeroval = pda->pio_write_status_val; 284 zeroval = pda->pio_write_status_val;
336 285
337 for (i=0; i < nix; i++) { 286
287 for (i=ib; i <= ie; i++) {
338 nasid = nasids[i]; 288 nasid = nasids[i];
339 if (!(sn2_ptctest & 3) && nasid == mynasid) 289 if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)
340 continue; 290 continue;
341 ptc0 = CHANGE_NASID(nasid, ptc0); 291 ptc0 = CHANGE_NASID(nasid, ptc0);
342 if (ptc1) 292 if (ptc1)
343 ptc1 = CHANGE_NASID(nasid, ptc1); 293 ptc1 = CHANGE_NASID(nasid, ptc1);
344 sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); 294
295 n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
296 __get_cpu_var(ptcstats).deadlocks2 += n;
345 } 297 }
346 298
347} 299}
@@ -452,20 +404,22 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data)
452 cpu = *(loff_t *) data; 404 cpu = *(loff_t *) data;
453 405
454 if (!cpu) { 406 if (!cpu) {
455 seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n"); 407 seq_printf(file,
408 "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n");
456 seq_printf(file, "# ptctest %d\n", sn2_ptctest); 409 seq_printf(file, "# ptctest %d\n", sn2_ptctest);
457 } 410 }
458 411
459 if (cpu < NR_CPUS && cpu_online(cpu)) { 412 if (cpu < NR_CPUS && cpu_online(cpu)) {
460 stat = &per_cpu(ptcstats, cpu); 413 stat = &per_cpu(ptcstats, cpu);
461 seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, 414 seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
462 stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, 415 stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
463 stat->deadlocks, 416 stat->deadlocks,
464 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 417 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
465 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 418 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
466 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec); 419 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
420 stat->shub_ptc_flushes_not_my_mm,
421 stat->deadlocks2);
467 } 422 }
468
469 return 0; 423 return 0;
470} 424}
471 425
@@ -476,7 +430,7 @@ static struct seq_operations sn2_ptc_seq_ops = {
476 .show = sn2_ptc_seq_show 430 .show = sn2_ptc_seq_show
477}; 431};
478 432
479int sn2_ptc_proc_open(struct inode *inode, struct file *file) 433static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
480{ 434{
481 return seq_open(file, &sn2_ptc_seq_ops); 435 return seq_open(file, &sn2_ptc_seq_ops);
482} 436}
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index c75f8aeefc2b..9cd460dfe27e 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -575,18 +575,21 @@ xpc_activate_partition(struct xpc_partition *part)
575 575
576 spin_lock_irqsave(&part->act_lock, irq_flags); 576 spin_lock_irqsave(&part->act_lock, irq_flags);
577 577
578 pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
579
580 DBUG_ON(part->act_state != XPC_P_INACTIVE); 578 DBUG_ON(part->act_state != XPC_P_INACTIVE);
581 579
582 if (pid > 0) { 580 part->act_state = XPC_P_ACTIVATION_REQ;
583 part->act_state = XPC_P_ACTIVATION_REQ; 581 XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
584 XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
585 } else {
586 XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
587 }
588 582
589 spin_unlock_irqrestore(&part->act_lock, irq_flags); 583 spin_unlock_irqrestore(&part->act_lock, irq_flags);
584
585 pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
586
587 if (unlikely(pid <= 0)) {
588 spin_lock_irqsave(&part->act_lock, irq_flags);
589 part->act_state = XPC_P_INACTIVE;
590 XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
591 spin_unlock_irqrestore(&part->act_lock, irq_flags);
592 }
590} 593}
591 594
592 595