Commit 4a5c13c7 authored by Mark Goodwin's avatar Mark Goodwin Committed by Tony Luck

[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: default avatarMark Goodwin <markgw@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 30325d17
...@@ -28,6 +28,7 @@ ...@@ -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 @@ ...@@ -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,27 +83,46 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) ...@@ -81,27 +83,46 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
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, bay, slot, slab;
int rack, slot, slab; int this_rack, this_bay, this_slot, this_slab;
int this_rack, 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, ...@@ -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) ...@@ -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, &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)) { if (SN_HWPERF_FOREIGN(obj)) {
...@@ -181,7 +255,7 @@ static int sn_topology_show(struct seq_file *s, void *d) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058
#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059
#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
...@@ -1012,4 +1013,14 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2, ...@@ -1012,4 +1013,14 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
return (int) rv.status; return (int) rv.status;
} }
static inline int
ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab,
char *buf, u64 len)
{
struct ia64_sal_retval rv;
SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY,
rack, bay, slot, slab, buf, len, 0);
return (int) rv.status;
}
#endif /* _ASM_IA64_SN_SN_SAL_H */ #endif /* _ASM_IA64_SN_SN_SAL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment