[IA64-SGI] Altix SN topology support for new chipsets and pci topology
authorMark Goodwin <markgw@sgi.com>
Mon, 25 Apr 2005 20:04:22 +0000 (13:04 -0700)
committerTony Luck <tony.luck@intel.com>
Mon, 25 Apr 2005 20:04:22 +0000 (13:04 -0700)
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>
arch/ia64/sn/kernel/sn2/sn_hwperf.c
include/asm-ia64/sn/sn_sal.h

index 1973564..3bff991 100644 (file)
@@ -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;
index 81a1cf1..410d356 100644 (file)
@@ -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 */