|
@@ -28,6 +28,7 @@
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/miscdevice.h>
|
|
|
|
+#include <linux/utsname.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/smp_lock.h>
|
|
#include <linux/smp_lock.h>
|
|
#include <linux/nodemask.h>
|
|
#include <linux/nodemask.h>
|
|
@@ -43,6 +44,7 @@
|
|
#include <asm/sn/module.h>
|
|
#include <asm/sn/module.h>
|
|
#include <asm/sn/geo.h>
|
|
#include <asm/sn/geo.h>
|
|
#include <asm/sn/sn2/sn_hwperf.h>
|
|
#include <asm/sn/sn2/sn_hwperf.h>
|
|
|
|
+#include <asm/sn/addrs.h>
|
|
|
|
|
|
static void *sn_hwperf_salheap = NULL;
|
|
static void *sn_hwperf_salheap = NULL;
|
|
static int sn_hwperf_obj_cnt = 0;
|
|
static int sn_hwperf_obj_cnt = 0;
|
|
@@ -81,26 +83,45 @@ out:
|
|
return e;
|
|
return e;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int sn_hwperf_location_to_bpos(char *location,
|
|
|
|
+ int *rack, int *bay, int *slot, int *slab)
|
|
|
|
+{
|
|
|
|
+ char type;
|
|
|
|
+
|
|
|
|
+ /* first scan for an old style geoid string */
|
|
|
|
+ if (sscanf(location, "%03d%c%02d#%d",
|
|
|
|
+ rack, &type, bay, slab) == 4)
|
|
|
|
+ *slot = 0;
|
|
|
|
+ else /* scan for a new bladed geoid string */
|
|
|
|
+ if (sscanf(location, "%03d%c%02d^%02d#%d",
|
|
|
|
+ rack, &type, bay, slot, slab) != 5)
|
|
|
|
+ return -1;
|
|
|
|
+ /* success */
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int sn_hwperf_geoid_to_cnode(char *location)
|
|
static int sn_hwperf_geoid_to_cnode(char *location)
|
|
{
|
|
{
|
|
int cnode;
|
|
int cnode;
|
|
geoid_t geoid;
|
|
geoid_t geoid;
|
|
moduleid_t module_id;
|
|
moduleid_t module_id;
|
|
- char type;
|
|
|
|
- int rack, slot, slab;
|
|
|
|
- int this_rack, this_slot, this_slab;
|
|
|
|
|
|
+ int rack, bay, slot, slab;
|
|
|
|
+ int this_rack, this_bay, this_slot, this_slab;
|
|
|
|
|
|
- if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4)
|
|
|
|
|
|
+ if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
for (cnode = 0; cnode < numionodes; cnode++) {
|
|
for (cnode = 0; cnode < numionodes; cnode++) {
|
|
geoid = cnodeid_get_geoid(cnode);
|
|
geoid = cnodeid_get_geoid(cnode);
|
|
module_id = geo_module(geoid);
|
|
module_id = geo_module(geoid);
|
|
this_rack = MODULE_GET_RACK(module_id);
|
|
this_rack = MODULE_GET_RACK(module_id);
|
|
- this_slot = MODULE_GET_BPOS(module_id);
|
|
|
|
|
|
+ this_bay = MODULE_GET_BPOS(module_id);
|
|
|
|
+ this_slot = 0; /* XXX */
|
|
this_slab = geo_slab(geoid);
|
|
this_slab = geo_slab(geoid);
|
|
- if (rack == this_rack && slot == this_slot && slab == this_slab)
|
|
|
|
|
|
+ if (rack == this_rack && bay == this_bay &&
|
|
|
|
+ slot == this_slot && slab == this_slab) {
|
|
break;
|
|
break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return cnode < numionodes ? cnode : -1;
|
|
return cnode < numionodes ? cnode : -1;
|
|
@@ -153,11 +174,29 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
|
|
return slabname;
|
|
return slabname;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void print_pci_topology(struct seq_file *s,
|
|
|
|
+ struct sn_hwperf_object_info *obj, int *ordinal,
|
|
|
|
+ char *pci_topo_buf, int len)
|
|
|
|
+{
|
|
|
|
+ char *p1;
|
|
|
|
+ char *p2;
|
|
|
|
+
|
|
|
|
+ for (p1=pci_topo_buf; *p1 && p1 < pci_topo_buf + len;) {
|
|
|
|
+ if (!(p2 = strchr(p1, '\n')))
|
|
|
|
+ break;
|
|
|
|
+ *p2 = '\0';
|
|
|
|
+ seq_printf(s, "pcibus %d %s-%s\n",
|
|
|
|
+ *ordinal, obj->location, p1);
|
|
|
|
+ (*ordinal)++;
|
|
|
|
+ p1 = p2 + 1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int sn_topology_show(struct seq_file *s, void *d)
|
|
static int sn_topology_show(struct seq_file *s, void *d)
|
|
{
|
|
{
|
|
int sz;
|
|
int sz;
|
|
int pt;
|
|
int pt;
|
|
- int e;
|
|
|
|
|
|
+ int e = 0;
|
|
int i;
|
|
int i;
|
|
int j;
|
|
int j;
|
|
const char *slabname;
|
|
const char *slabname;
|
|
@@ -169,11 +208,46 @@ static int sn_topology_show(struct seq_file *s, void *d)
|
|
struct sn_hwperf_object_info *p;
|
|
struct sn_hwperf_object_info *p;
|
|
struct sn_hwperf_object_info *obj = d; /* this object */
|
|
struct sn_hwperf_object_info *obj = d; /* this object */
|
|
struct sn_hwperf_object_info *objs = s->private; /* all objects */
|
|
struct sn_hwperf_object_info *objs = s->private; /* all objects */
|
|
|
|
+ int rack, bay, slot, slab;
|
|
|
|
+ u8 shubtype;
|
|
|
|
+ u8 system_size;
|
|
|
|
+ u8 sharing_size;
|
|
|
|
+ u8 partid;
|
|
|
|
+ u8 coher;
|
|
|
|
+ u8 nasid_shift;
|
|
|
|
+ u8 region_size;
|
|
|
|
+ u16 nasid_mask;
|
|
|
|
+ int nasid_msb;
|
|
|
|
+ char *pci_topo_buf;
|
|
|
|
+ int pci_bus_ordinal = 0;
|
|
|
|
+ static int pci_topo_buf_len = 256;
|
|
|
|
|
|
if (obj == objs) {
|
|
if (obj == objs) {
|
|
- seq_printf(s, "# sn_topology version 1\n");
|
|
|
|
|
|
+ seq_printf(s, "# sn_topology version 2\n");
|
|
seq_printf(s, "# objtype ordinal location partition"
|
|
seq_printf(s, "# objtype ordinal location partition"
|
|
" [attribute value [, ...]]\n");
|
|
" [attribute value [, ...]]\n");
|
|
|
|
+
|
|
|
|
+ if (ia64_sn_get_sn_info(0,
|
|
|
|
+ &shubtype, &nasid_mask, &nasid_shift, &system_size,
|
|
|
|
+ &sharing_size, &partid, &coher, ®ion_size))
|
|
|
|
+ BUG();
|
|
|
|
+ for (nasid_msb=63; nasid_msb > 0; nasid_msb--) {
|
|
|
|
+ if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb))
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ seq_printf(s, "partition %u %s local "
|
|
|
|
+ "shubtype %s, "
|
|
|
|
+ "nasid_mask 0x%016lx, "
|
|
|
|
+ "nasid_bits %d:%d, "
|
|
|
|
+ "system_size %d, "
|
|
|
|
+ "sharing_size %d, "
|
|
|
|
+ "coherency_domain %d, "
|
|
|
|
+ "region_size %d\n",
|
|
|
|
+
|
|
|
|
+ partid, system_utsname.nodename,
|
|
|
|
+ shubtype ? "shub2" : "shub1",
|
|
|
|
+ (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
|
|
|
|
+ system_size, sharing_size, coher, region_size);
|
|
}
|
|
}
|
|
|
|
|
|
if (SN_HWPERF_FOREIGN(obj)) {
|
|
if (SN_HWPERF_FOREIGN(obj)) {
|
|
@@ -181,7 +255,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 0; obj->name[i]; i++) {
|
|
|
|
|
|
+ for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
|
|
if (obj->name[i] == ' ')
|
|
if (obj->name[i] == ' ')
|
|
obj->name[i] = '_';
|
|
obj->name[i] = '_';
|
|
}
|
|
}
|
|
@@ -221,6 +295,43 @@ static int sn_topology_show(struct seq_file *s, void *d)
|
|
seq_putc(s, '\n');
|
|
seq_putc(s, '\n');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * PCI busses attached to this node, if any
|
|
|
|
+ */
|
|
|
|
+ do {
|
|
|
|
+ if (!(pci_topo_buf = vmalloc(pci_topo_buf_len))) {
|
|
|
|
+ printk("sn_topology_show: kmalloc failed\n");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sn_hwperf_location_to_bpos(obj->location,
|
|
|
|
+ &rack, &bay, &slot, &slab) != 0)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ e = ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab,
|
|
|
|
+ pci_topo_buf, pci_topo_buf_len);
|
|
|
|
+
|
|
|
|
+ switch (e) {
|
|
|
|
+ case SALRET_NOT_IMPLEMENTED:
|
|
|
|
+ case SALRET_INVALID_ARG:
|
|
|
|
+ /* ignore, don't print anything */
|
|
|
|
+ e = SN_HWPERF_OP_OK;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SALRET_ERROR:
|
|
|
|
+ /* retry with a bigger buffer */
|
|
|
|
+ pci_topo_buf_len += 256;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SN_HWPERF_OP_OK:
|
|
|
|
+ /* export pci bus info */
|
|
|
|
+ print_pci_topology(s, obj, &pci_bus_ordinal,
|
|
|
|
+ pci_topo_buf, pci_topo_buf_len);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ vfree(pci_topo_buf);
|
|
|
|
+ } while (e != SN_HWPERF_OP_OK && pci_topo_buf_len < 0x200000);
|
|
}
|
|
}
|
|
|
|
|
|
if (obj->ports) {
|
|
if (obj->ports) {
|
|
@@ -397,6 +508,9 @@ static int sn_hwperf_map_err(int hwperf_err)
|
|
break;
|
|
break;
|
|
|
|
|
|
case SN_HWPERF_OP_BUSY:
|
|
case SN_HWPERF_OP_BUSY:
|
|
|
|
+ e = -EBUSY;
|
|
|
|
+ break;
|
|
|
|
+
|
|
case SN_HWPERF_OP_RECONFIGURE:
|
|
case SN_HWPERF_OP_RECONFIGURE:
|
|
e = -EAGAIN;
|
|
e = -EAGAIN;
|
|
break;
|
|
break;
|
|
@@ -549,6 +663,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
|
|
r = sn_hwperf_op_cpu(&op_info);
|
|
r = sn_hwperf_op_cpu(&op_info);
|
|
if (r) {
|
|
if (r) {
|
|
r = sn_hwperf_map_err(r);
|
|
r = sn_hwperf_map_err(r);
|
|
|
|
+ a.v0 = v0;
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
break;
|
|
break;
|