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/io_init.c45
-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/sn2_smp.c196
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c6
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c19
7 files changed, 150 insertions, 185 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 00700f7e6837..d7e4d79e16a8 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -10,6 +10,7 @@
10#include <linux/nodemask.h> 10#include <linux/nodemask.h>
11#include <asm/sn/types.h> 11#include <asm/sn/types.h>
12#include <asm/sn/addrs.h> 12#include <asm/sn/addrs.h>
13#include <asm/sn/sn_feature_sets.h>
13#include <asm/sn/geo.h> 14#include <asm/sn/geo.h>
14#include <asm/sn/io.h> 15#include <asm/sn/io.h>
15#include <asm/sn/pcibr_provider.h> 16#include <asm/sn/pcibr_provider.h>
@@ -173,8 +174,8 @@ sn_pcidev_info_get(struct pci_dev *dev)
173 */ 174 */
174static u8 war_implemented = 0; 175static u8 war_implemented = 0;
175 176
176static void sn_device_fixup_war(u64 nasid, u64 widget, int device, 177static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
177 struct sn_flush_device_common *common) 178 struct sn_flush_device_common *common)
178{ 179{
179 struct sn_flush_device_war *war_list; 180 struct sn_flush_device_war *war_list;
180 struct sn_flush_device_war *dev_entry; 181 struct sn_flush_device_war *dev_entry;
@@ -198,15 +199,16 @@ static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
198 199
199 dev_entry = war_list + device; 200 dev_entry = war_list + device;
200 memcpy(common,dev_entry, sizeof(*common)); 201 memcpy(common,dev_entry, sizeof(*common));
201
202 kfree(war_list); 202 kfree(war_list);
203
204 return isrv.status;
203} 205}
204 206
205/* 207/*
206 * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 208 * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
207 * each node in the system. 209 * each node in the system.
208 */ 210 */
209static void sn_fixup_ionodes(void) 211static void __init sn_fixup_ionodes(void)
210{ 212{
211 struct sn_flush_device_kernel *sn_flush_device_kernel; 213 struct sn_flush_device_kernel *sn_flush_device_kernel;
212 struct sn_flush_device_kernel *dev_entry; 214 struct sn_flush_device_kernel *dev_entry;
@@ -279,23 +281,21 @@ static void sn_fixup_ionodes(void)
279 memset(dev_entry->common, 0x0, sizeof(struct 281 memset(dev_entry->common, 0x0, sizeof(struct
280 sn_flush_device_common)); 282 sn_flush_device_common));
281 283
282 status = sal_get_device_dmaflush_list(nasid, 284 if (sn_prom_feature_available(
283 widget, 285 PRF_DEVICE_FLUSH_LIST))
284 device, 286 status = sal_get_device_dmaflush_list(
287 nasid,
288 widget,
289 device,
285 (u64)(dev_entry->common)); 290 (u64)(dev_entry->common));
286 if (status) { 291 else
287 if (sn_sal_rev() < 0x0450) { 292 status = sn_device_fixup_war(nasid,
288 /* shortlived WAR for older 293 widget,
289 * PROM images 294 device,
290 */
291 sn_device_fixup_war(nasid,
292 widget,
293 device,
294 dev_entry->common); 295 dev_entry->common);
295 } 296 if (status != SALRET_OK)
296 else 297 panic("SAL call failed: %s\n",
297 BUG(); 298 ia64_sal_strerror(status));
298 }
299 299
300 spin_lock_init(&dev_entry->sfdl_flush_lock); 300 spin_lock_init(&dev_entry->sfdl_flush_lock);
301 } 301 }
@@ -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/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_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 8d950c778bb6..36e5437a0fb6 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -447,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
447 447
448 nbytes = nentries * ch->msg_size; 448 nbytes = nentries * ch->msg_size;
449 ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, 449 ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
450 (GFP_KERNEL | GFP_DMA), 450 GFP_KERNEL,
451 &ch->local_msgqueue_base); 451 &ch->local_msgqueue_base);
452 if (ch->local_msgqueue == NULL) { 452 if (ch->local_msgqueue == NULL) {
453 continue; 453 continue;
@@ -455,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
455 memset(ch->local_msgqueue, 0, nbytes); 455 memset(ch->local_msgqueue, 0, nbytes);
456 456
457 nbytes = nentries * sizeof(struct xpc_notify); 457 nbytes = nentries * sizeof(struct xpc_notify);
458 ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA)); 458 ch->notify_queue = kmalloc(nbytes, GFP_KERNEL);
459 if (ch->notify_queue == NULL) { 459 if (ch->notify_queue == NULL) {
460 kfree(ch->local_msgqueue_base); 460 kfree(ch->local_msgqueue_base);
461 ch->local_msgqueue = NULL; 461 ch->local_msgqueue = NULL;
@@ -502,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
502 502
503 nbytes = nentries * ch->msg_size; 503 nbytes = nentries * ch->msg_size;
504 ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, 504 ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
505 (GFP_KERNEL | GFP_DMA), 505 GFP_KERNEL,
506 &ch->remote_msgqueue_base); 506 &ch->remote_msgqueue_base);
507 if (ch->remote_msgqueue == NULL) { 507 if (ch->remote_msgqueue == NULL) {
508 continue; 508 continue;
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