aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c133
-rw-r--r--include/asm-ia64/sn/sn_sal.h11
2 files changed, 135 insertions, 9 deletions
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 197356460ee1..3bff99130d5e 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -28,6 +28,7 @@
28#include <linux/vmalloc.h> 28#include <linux/vmalloc.h>
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/miscdevice.h> 30#include <linux/miscdevice.h>
31#include <linux/utsname.h>
31#include <linux/cpumask.h> 32#include <linux/cpumask.h>
32#include <linux/smp_lock.h> 33#include <linux/smp_lock.h>
33#include <linux/nodemask.h> 34#include <linux/nodemask.h>
@@ -43,6 +44,7 @@
43#include <asm/sn/module.h> 44#include <asm/sn/module.h>
44#include <asm/sn/geo.h> 45#include <asm/sn/geo.h>
45#include <asm/sn/sn2/sn_hwperf.h> 46#include <asm/sn/sn2/sn_hwperf.h>
47#include <asm/sn/addrs.h>
46 48
47static void *sn_hwperf_salheap = NULL; 49static void *sn_hwperf_salheap = NULL;
48static int sn_hwperf_obj_cnt = 0; 50static int sn_hwperf_obj_cnt = 0;
@@ -81,26 +83,45 @@ out:
81 return e; 83 return e;
82} 84}
83 85
86static int sn_hwperf_location_to_bpos(char *location,
87 int *rack, int *bay, int *slot, int *slab)
88{
89 char type;
90
91 /* first scan for an old style geoid string */
92 if (sscanf(location, "%03d%c%02d#%d",
93 rack, &type, bay, slab) == 4)
94 *slot = 0;
95 else /* scan for a new bladed geoid string */
96 if (sscanf(location, "%03d%c%02d^%02d#%d",
97 rack, &type, bay, slot, slab) != 5)
98 return -1;
99 /* success */
100 return 0;
101}
102
84static int sn_hwperf_geoid_to_cnode(char *location) 103static int sn_hwperf_geoid_to_cnode(char *location)
85{ 104{
86 int cnode; 105 int cnode;
87 geoid_t geoid; 106 geoid_t geoid;
88 moduleid_t module_id; 107 moduleid_t module_id;
89 char type; 108 int rack, bay, slot, slab;
90 int rack, slot, slab; 109 int this_rack, this_bay, this_slot, this_slab;
91 int this_rack, this_slot, this_slab;
92 110
93 if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4) 111 if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
94 return -1; 112 return -1;
95 113
96 for (cnode = 0; cnode < numionodes; cnode++) { 114 for (cnode = 0; cnode < numionodes; cnode++) {
97 geoid = cnodeid_get_geoid(cnode); 115 geoid = cnodeid_get_geoid(cnode);
98 module_id = geo_module(geoid); 116 module_id = geo_module(geoid);
99 this_rack = MODULE_GET_RACK(module_id); 117 this_rack = MODULE_GET_RACK(module_id);
100 this_slot = MODULE_GET_BPOS(module_id); 118 this_bay = MODULE_GET_BPOS(module_id);
119 this_slot = 0; /* XXX */
101 this_slab = geo_slab(geoid); 120 this_slab = geo_slab(geoid);
102 if (rack == this_rack && slot == this_slot && slab == this_slab) 121 if (rack == this_rack && bay == this_bay &&
122 slot == this_slot && slab == this_slab) {
103 break; 123 break;
124 }
104 } 125 }
105 126
106 return cnode < numionodes ? cnode : -1; 127 return cnode < numionodes ? cnode : -1;
@@ -153,11 +174,29 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
153 return slabname; 174 return slabname;
154} 175}
155 176
177static void print_pci_topology(struct seq_file *s,
178 struct sn_hwperf_object_info *obj, int *ordinal,
179 char *pci_topo_buf, int len)
180{
181 char *p1;
182 char *p2;
183
184 for (p1=pci_topo_buf; *p1 && p1 < pci_topo_buf + len;) {
185 if (!(p2 = strchr(p1, '\n')))
186 break;
187 *p2 = '\0';
188 seq_printf(s, "pcibus %d %s-%s\n",
189 *ordinal, obj->location, p1);
190 (*ordinal)++;
191 p1 = p2 + 1;
192 }
193}
194
156static int sn_topology_show(struct seq_file *s, void *d) 195static int sn_topology_show(struct seq_file *s, void *d)
157{ 196{
158 int sz; 197 int sz;
159 int pt; 198 int pt;
160 int e; 199 int e = 0;
161 int i; 200 int i;
162 int j; 201 int j;
163 const char *slabname; 202 const char *slabname;
@@ -169,11 +208,46 @@ static int sn_topology_show(struct seq_file *s, void *d)
169 struct sn_hwperf_object_info *p; 208 struct sn_hwperf_object_info *p;
170 struct sn_hwperf_object_info *obj = d; /* this object */ 209 struct sn_hwperf_object_info *obj = d; /* this object */
171 struct sn_hwperf_object_info *objs = s->private; /* all objects */ 210 struct sn_hwperf_object_info *objs = s->private; /* all objects */
211 int rack, bay, slot, slab;
212 u8 shubtype;
213 u8 system_size;
214 u8 sharing_size;
215 u8 partid;
216 u8 coher;
217 u8 nasid_shift;
218 u8 region_size;
219 u16 nasid_mask;
220 int nasid_msb;
221 char *pci_topo_buf;
222 int pci_bus_ordinal = 0;
223 static int pci_topo_buf_len = 256;
172 224
173 if (obj == objs) { 225 if (obj == objs) {
174 seq_printf(s, "# sn_topology version 1\n"); 226 seq_printf(s, "# sn_topology version 2\n");
175 seq_printf(s, "# objtype ordinal location partition" 227 seq_printf(s, "# objtype ordinal location partition"
176 " [attribute value [, ...]]\n"); 228 " [attribute value [, ...]]\n");
229
230 if (ia64_sn_get_sn_info(0,
231 &shubtype, &nasid_mask, &nasid_shift, &system_size,
232 &sharing_size, &partid, &coher, &region_size))
233 BUG();
234 for (nasid_msb=63; nasid_msb > 0; nasid_msb--) {
235 if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb))
236 break;
237 }
238 seq_printf(s, "partition %u %s local "
239 "shubtype %s, "
240 "nasid_mask 0x%016lx, "
241 "nasid_bits %d:%d, "
242 "system_size %d, "
243 "sharing_size %d, "
244 "coherency_domain %d, "
245 "region_size %d\n",
246
247 partid, system_utsname.nodename,
248 shubtype ? "shub2" : "shub1",
249 (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
250 system_size, sharing_size, coher, region_size);
177 } 251 }
178 252
179 if (SN_HWPERF_FOREIGN(obj)) { 253 if (SN_HWPERF_FOREIGN(obj)) {
@@ -181,7 +255,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
181 return 0; 255 return 0;
182 } 256 }
183 257
184 for (i = 0; obj->name[i]; i++) { 258 for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
185 if (obj->name[i] == ' ') 259 if (obj->name[i] == ' ')
186 obj->name[i] = '_'; 260 obj->name[i] = '_';
187 } 261 }
@@ -221,6 +295,43 @@ static int sn_topology_show(struct seq_file *s, void *d)
221 seq_putc(s, '\n'); 295 seq_putc(s, '\n');
222 } 296 }
223 } 297 }
298
299 /*
300 * PCI busses attached to this node, if any
301 */
302 do {
303 if (!(pci_topo_buf = vmalloc(pci_topo_buf_len))) {
304 printk("sn_topology_show: kmalloc failed\n");
305 break;
306 }
307
308 if (sn_hwperf_location_to_bpos(obj->location,
309 &rack, &bay, &slot, &slab) != 0)
310 continue;
311
312 e = ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab,
313 pci_topo_buf, pci_topo_buf_len);
314
315 switch (e) {
316 case SALRET_NOT_IMPLEMENTED:
317 case SALRET_INVALID_ARG:
318 /* ignore, don't print anything */
319 e = SN_HWPERF_OP_OK;
320 break;
321
322 case SALRET_ERROR:
323 /* retry with a bigger buffer */
324 pci_topo_buf_len += 256;
325 break;
326
327 case SN_HWPERF_OP_OK:
328 /* export pci bus info */
329 print_pci_topology(s, obj, &pci_bus_ordinal,
330 pci_topo_buf, pci_topo_buf_len);
331 break;
332 }
333 vfree(pci_topo_buf);
334 } while (e != SN_HWPERF_OP_OK && pci_topo_buf_len < 0x200000);
224 } 335 }
225 336
226 if (obj->ports) { 337 if (obj->ports) {
@@ -397,6 +508,9 @@ static int sn_hwperf_map_err(int hwperf_err)
397 break; 508 break;
398 509
399 case SN_HWPERF_OP_BUSY: 510 case SN_HWPERF_OP_BUSY:
511 e = -EBUSY;
512 break;
513
400 case SN_HWPERF_OP_RECONFIGURE: 514 case SN_HWPERF_OP_RECONFIGURE:
401 e = -EAGAIN; 515 e = -EAGAIN;
402 break; 516 break;
@@ -549,6 +663,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
549 r = sn_hwperf_op_cpu(&op_info); 663 r = sn_hwperf_op_cpu(&op_info);
550 if (r) { 664 if (r) {
551 r = sn_hwperf_map_err(r); 665 r = sn_hwperf_map_err(r);
666 a.v0 = v0;
552 goto error; 667 goto error;
553 } 668 }
554 break; 669 break;
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 81a1cf1e4f5a..410d356b40da 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -74,6 +74,7 @@
74#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 74#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
75#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 75#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
76#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 76#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058
77#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059
77 78
78#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 79#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
79 80
@@ -1012,4 +1013,14 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
1012 return (int) rv.status; 1013 return (int) rv.status;
1013} 1014}
1014 1015
1016static inline int
1017ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab,
1018 char *buf, u64 len)
1019{
1020 struct ia64_sal_retval rv;
1021 SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY,
1022 rack, bay, slot, slab, buf, len, 0);
1023 return (int) rv.status;
1024}
1025
1015#endif /* _ASM_IA64_SN_SN_SAL_H */ 1026#endif /* _ASM_IA64_SN_SN_SAL_H */