aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2006-05-31 09:58:08 -0400
committerTony Luck <tony.luck@intel.com>2006-06-21 17:33:56 -0400
commita1d7057727bc9e20a0a417812f538fe6b8a02c03 (patch)
treebd3627eb3ea4b916dd1de521c341b92e3444f4dd /arch/ia64/sn
parent5eb1d63f5fc8455269c2756223b3cf3779fd2f7a (diff)
[IA64-SGI] SN topology fix for large systems
There is an SN bug in sn_hwperf.c that affects systems with 1024n or 1024p. The bug manifests itself 2 ways: IO interrupts are not always targeted to the nearest node, and 2) the "cat /proc/sgi_sn/sn_topology" commands fails with "cannot allocate memory". The code is using the wrong macros for validating node numbers. Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/sn')
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 739c948dc504..9a8a29339d2d 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -51,6 +51,8 @@ static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
51static int sn_hwperf_init(void); 51static int sn_hwperf_init(void);
52static DECLARE_MUTEX(sn_hwperf_init_mutex); 52static DECLARE_MUTEX(sn_hwperf_init_mutex);
53 53
54#define cnode_possible(n) ((n) < num_cnodes)
55
54static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) 56static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
55{ 57{
56 int e; 58 int e;
@@ -127,14 +129,14 @@ static int sn_hwperf_geoid_to_cnode(char *location)
127 } 129 }
128 } 130 }
129 131
130 return node_possible(cnode) ? cnode : -1; 132 return cnode_possible(cnode) ? cnode : -1;
131} 133}
132 134
133static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) 135static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
134{ 136{
135 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) 137 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
136 BUG(); 138 BUG();
137 if (!obj->sn_hwp_this_part) 139 if (SN_HWPERF_FOREIGN(obj))
138 return -1; 140 return -1;
139 return sn_hwperf_geoid_to_cnode(obj->location); 141 return sn_hwperf_geoid_to_cnode(obj->location);
140} 142}
@@ -199,12 +201,12 @@ static void print_pci_topology(struct seq_file *s)
199 201
200static inline int sn_hwperf_has_cpus(cnodeid_t node) 202static inline int sn_hwperf_has_cpus(cnodeid_t node)
201{ 203{
202 return node_online(node) && nr_cpus_node(node); 204 return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node);
203} 205}
204 206
205static inline int sn_hwperf_has_mem(cnodeid_t node) 207static inline int sn_hwperf_has_mem(cnodeid_t node)
206{ 208{
207 return node_online(node) && NODE_DATA(node)->node_present_pages; 209 return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages;
208} 210}
209 211
210static struct sn_hwperf_object_info * 212static struct sn_hwperf_object_info *
@@ -237,7 +239,7 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
237 int found_mem = 0; 239 int found_mem = 0;
238 int found_cpu = 0; 240 int found_cpu = 0;
239 241
240 if (!node_possible(node)) 242 if (!cnode_possible(node))
241 return -EINVAL; 243 return -EINVAL;
242 244
243 if (sn_hwperf_has_cpus(node)) { 245 if (sn_hwperf_has_cpus(node)) {
@@ -442,7 +444,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
442 seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, 444 seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location,
443 obj->sn_hwp_this_part ? "local" : "shared", obj->name); 445 obj->sn_hwp_this_part ? "local" : "shared", obj->name);
444 446
445 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) 447 if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)))
446 seq_putc(s, '\n'); 448 seq_putc(s, '\n');
447 else { 449 else {
448 cnodeid_t near_mem = -1; 450 cnodeid_t near_mem = -1;
@@ -468,22 +470,24 @@ static int sn_topology_show(struct seq_file *s, void *d)
468 /* 470 /*
469 * CPUs on this node, if any 471 * CPUs on this node, if any
470 */ 472 */
471 cpumask = node_to_cpumask(ordinal); 473 if (!SN_HWPERF_IS_IONODE(obj)) {
472 for_each_online_cpu(i) { 474 cpumask = node_to_cpumask(ordinal);
473 if (cpu_isset(i, cpumask)) { 475 for_each_online_cpu(i) {
474 slice = 'a' + cpuid_to_slice(i); 476 if (cpu_isset(i, cpumask)) {
475 c = cpu_data(i); 477 slice = 'a' + cpuid_to_slice(i);
476 seq_printf(s, "cpu %d %s%c local" 478 c = cpu_data(i);
477 " freq %luMHz, arch ia64", 479 seq_printf(s, "cpu %d %s%c local"
478 i, obj->location, slice, 480 " freq %luMHz, arch ia64",
479 c->proc_freq / 1000000); 481 i, obj->location, slice,
480 for_each_online_cpu(j) { 482 c->proc_freq / 1000000);
481 seq_printf(s, j ? ":%d" : ", dist %d", 483 for_each_online_cpu(j) {
482 node_distance( 484 seq_printf(s, j ? ":%d" : ", dist %d",
483 cpu_to_node(i), 485 node_distance(
484 cpu_to_node(j))); 486 cpu_to_node(i),
487 cpu_to_node(j)));
488 }
489 seq_putc(s, '\n');
485 } 490 }
486 seq_putc(s, '\n');
487 } 491 }
488 } 492 }
489 } 493 }
@@ -523,7 +527,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
523 if (obj->sn_hwp_this_part && p->sn_hwp_this_part) 527 if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
524 /* both ends local to this partition */ 528 /* both ends local to this partition */
525 seq_puts(s, " local"); 529 seq_puts(s, " local");
526 else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part) 530 else if (SN_HWPERF_FOREIGN(p))
527 /* both ends of the link in foreign partiton */ 531 /* both ends of the link in foreign partiton */
528 seq_puts(s, " foreign"); 532 seq_puts(s, " foreign");
529 else 533 else
@@ -776,7 +780,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
776 780
777 case SN_HWPERF_GET_NODE_NASID: 781 case SN_HWPERF_GET_NODE_NASID:
778 if (a.sz != sizeof(u64) || 782 if (a.sz != sizeof(u64) ||
779 (node = a.arg) < 0 || !node_possible(node)) { 783 (node = a.arg) < 0 || !cnode_possible(node)) {
780 r = -EINVAL; 784 r = -EINVAL;
781 goto error; 785 goto error;
782 } 786 }