summaryrefslogtreecommitdiff
path: root/arch/ia64/sn/kernel/sn2
diff options
context:
space:
mode:
authorMark Goodwin <markgw@sgi.com>2005-04-25 13:04:22 -0700
committerTony Luck <tony.luck@intel.com>2005-04-25 13:04:22 -0700
commit4a5c13c7eb0d55bfd2cf3100c55f1e3d8df37576 (patch)
tree400e51f79f9ba6d34c66401e1760a51e792d14aa /arch/ia64/sn/kernel/sn2
parent30325d17715302a60c9afdaacaafaeb056b7e880 (diff)
[IA64-SGI] Altix SN topology support for new chipsets and pci topology
please accept this patch to the Altix SN platform topology export interface to support new chipsets and to export PCI topology. This follows on top of Jack Steiner's patch dated March 1st ("New chipset support for SN platform"). Signed-off-by: Mark Goodwin <markgw@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/sn/kernel/sn2')
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c133
1 files changed, 124 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 @@
#include <linux/vmalloc.h>
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
+#include <linux/utsname.h>
#include <linux/cpumask.h>
#include <linux/smp_lock.h>
#include <linux/nodemask.h>
@@ -43,6 +44,7 @@
#include <asm/sn/module.h>
#include <asm/sn/geo.h>
#include <asm/sn/sn2/sn_hwperf.h>
+#include <asm/sn/addrs.h>
static void *sn_hwperf_salheap = NULL;
static int sn_hwperf_obj_cnt = 0;
@@ -81,26 +83,45 @@ out:
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)
{
int cnode;
geoid_t geoid;
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;
for (cnode = 0; cnode < numionodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
module_id = geo_module(geoid);
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);
- if (rack == this_rack && slot == this_slot && slab == this_slab)
+ if (rack == this_rack && bay == this_bay &&
+ slot == this_slot && slab == this_slab) {
break;
+ }
}
return cnode < numionodes ? cnode : -1;
@@ -153,11 +174,29 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
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)
{
int sz;
int pt;
- int e;
+ int e = 0;
int i;
int j;
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 *obj = d; /* this object */
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) {
- seq_printf(s, "# sn_topology version 1\n");
+ seq_printf(s, "# sn_topology version 2\n");
seq_printf(s, "# objtype ordinal location partition"
" [attribute value [, ...]]\n");
+
+ if (ia64_sn_get_sn_info(0,
+ &shubtype, &nasid_mask, &nasid_shift, &system_size,
+ &sharing_size, &partid, &coher, &region_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)) {
@@ -181,7 +255,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
return 0;
}
- for (i = 0; obj->name[i]; i++) {
+ for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
if (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');
}
}
+
+ /*
+ * 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) {
@@ -397,6 +508,9 @@ static int sn_hwperf_map_err(int hwperf_err)
break;
case SN_HWPERF_OP_BUSY:
+ e = -EBUSY;
+ break;
+
case SN_HWPERF_OP_RECONFIGURE:
e = -EAGAIN;
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);
if (r) {
r = sn_hwperf_map_err(r);
+ a.v0 = v0;
goto error;
}
break;