diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-06 18:46:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-06 18:46:39 -0500 |
commit | c03296a868ae7c91aa2d8b372184763b18f16d7a (patch) | |
tree | 57ff0b44a412b78fe598a49cc28b3cebf51f1154 /arch/ia64/sn/kernel | |
parent | e3f749c4af69c4344d89f11e2293e3790eb4eaca (diff) | |
parent | 913e4a75572354995b330f57082d9a86250cd75f (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
Diffstat (limited to 'arch/ia64/sn/kernel')
-rw-r--r-- | arch/ia64/sn/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/bte.c | 17 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 9 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/irq.c | 21 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/klconflib.c | 29 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 19 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 196 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/xpc_main.c | 19 |
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 | ||
10 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
11 | |||
10 | obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ | 12 | obj-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/ |
12 | obj-$(CONFIG_IA64_GENERIC) += machvec.o | 14 | obj-$(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 | */ |
211 | static void sn_fixup_ionodes(void) | 211 | static 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 | ||
77 | static void sn_ack_irq(unsigned int irq) | 78 | static 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 | ||
92 | static void sn_end_irq(unsigned int irq) | 91 | static 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 | ||
227 | static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) | 225 | static 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 | ||
295 | void sn_irq_unfixup(struct pci_dev *pci_dev) | 293 | void 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 | ||
422 | void sn_irq_lh_init(void) | 420 | void __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 | ||
211 | extern int platform_intr_list[]; | 211 | extern int platform_intr_list[]; |
212 | static int __initdata shub_1_1_found = 0; | 212 | static 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 | ||
12 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
13 | |||
12 | obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ | 14 | obj-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 | ||
47 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); | 47 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); |
48 | 48 | ||
49 | void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, | 49 | void 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 | |||
71 | static unsigned int sn2_ptctest = 0; | ||
72 | |||
73 | static int __init ptc_test(char *str) | ||
74 | { | ||
75 | get_option(&str, &sn2_ptctest); | ||
76 | return 1; | ||
77 | } | ||
78 | __setup("ptctest=", ptc_test); | ||
79 | |||
80 | static 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 | |||
108 | static 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 | ||
136 | static inline int ptc_lock(unsigned long *flagp) | 62 | static 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 | ||
142 | static inline void ptc_unlock(unsigned long flags, int opt) | 67 | static 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 | ||
148 | struct ptc_stats { | 72 | struct 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 | ||
159 | static inline unsigned long wait_piowc(void) | 85 | static 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 | ||
172 | void sn_tlb_migrate_finish(struct mm_struct *mm) | 98 | void 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 | |||
201 | sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | 128 | sn2_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 | */ |
324 | void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, | 273 | void 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 | ||
479 | int sn2_ptc_proc_open(struct inode *inode, struct file *file) | 433 | static 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 | ||