[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>
This commit is contained in:
parent
30325d1771
commit
4a5c13c7eb
2 changed files with 135 additions and 9 deletions
|
@ -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 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
|
|||
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, ®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)) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
|
||||
#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
|
||||
#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058
|
||||
#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059
|
||||
|
||||
#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,
|
|||
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 */
|
||||
|
|
Loading…
Reference in a new issue