X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fia64%2Fsn%2Fkernel%2Fsn2%2Fsn_hwperf.c;h=197356460ee15d57d1665ea9a70618540266ed08;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=8a810d339e2f1524601902328271ecf852ba0790;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 8a810d339..197356460 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved. * * SGI Altix topology and hardware performance monitoring API. * Mark Goodwin . @@ -30,15 +30,19 @@ #include #include #include +#include #include #include #include #include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include static void *sn_hwperf_salheap = NULL; static int sn_hwperf_obj_cnt = 0; @@ -80,21 +84,26 @@ out: static int sn_hwperf_geoid_to_cnode(char *location) { int cnode; - int mod, slot, slab; - int cmod, cslot, cslab; + geoid_t geoid; + moduleid_t module_id; + char type; + int rack, slot, slab; + int this_rack, this_slot, this_slab; - if (sscanf(location, "%03dc%02d#%d", &mod, &slot, &slab) != 3) + if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4) return -1; - for (cnode = 0; cnode < numnodes; cnode++) { - /* XXX: need a better way than this ... */ - if (sscanf(NODEPDA(cnode)->hwg_node_name, - "hw/module/%03dc%02d/slab/%d", &cmod, &cslot, &cslab) == 3) { - if (mod == cmod && slot == cslot && slab == cslab) - break; - } + + 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_slab = geo_slab(geoid); + if (rack == this_rack && slot == this_slot && slab == this_slab) + break; } - return cnode < numnodes ? cnode : -1; + return cnode < numionodes ? cnode : -1; } static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) @@ -113,52 +122,35 @@ static int sn_hwperf_generic_ordinal(struct sn_hwperf_object_info *obj, for (ordinal=0, p=objs; p != obj; p++) { if (SN_HWPERF_FOREIGN(p)) continue; - if (p->location[3] == obj->location[3]) + if (SN_HWPERF_SAME_OBJTYPE(p, obj)) ordinal++; } return ordinal; } -#ifndef MODULE_IOBRICK -/* this will be available when ioif TIO support is added */ -#define MODULE_IOBRICK (MODULE_OPUSBRICK+1) -#endif +static const char *slabname_node = "node"; /* SHub asic */ +static const char *slabname_ionode = "ionode"; /* TIO asic */ +static const char *slabname_router = "router"; /* NL3R or NL4R */ +static const char *slabname_other = "other"; /* unknown asic */ -static const char *sn_hwperf_get_brickname(struct sn_hwperf_object_info *obj, - struct sn_hwperf_object_info *objs, int *ordinal) +static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj, + struct sn_hwperf_object_info *objs, int *ordinal) { - int i; - const char *objtype = NULL; + int isnode; + const char *slabname = slabname_other; - for (i=0; i < MAX_BRICK_TYPES; i++) { - if (brick_types[i] != obj->location[3]) - continue; - switch (i) { - case MODULE_CBRICK: - objtype = "node"; - *ordinal = sn_hwperf_obj_to_cnode(obj); /* cnodeid */ - break; - - case MODULE_RBRICK: - objtype = "router"; - *ordinal = sn_hwperf_generic_ordinal(obj, objs); - break; - - case MODULE_IOBRICK: - objtype = "ionode"; - *ordinal = sn_hwperf_generic_ordinal(obj, objs); - break; - } - break; + if ((isnode = SN_HWPERF_IS_NODE(obj)) || SN_HWPERF_IS_IONODE(obj)) { + slabname = isnode ? slabname_node : slabname_ionode; + *ordinal = sn_hwperf_obj_to_cnode(obj); } - - if (i == MAX_BRICK_TYPES) { - objtype = "other"; + else { *ordinal = sn_hwperf_generic_ordinal(obj, objs); + if (SN_HWPERF_IS_ROUTER(obj)) + slabname = slabname_router; } - return objtype; + return slabname; } static int sn_topology_show(struct seq_file *s, void *d) @@ -168,7 +160,7 @@ static int sn_topology_show(struct seq_file *s, void *d) int e; int i; int j; - const char *brickname; + const char *slabname; int ordinal; cpumask_t cpumask; char slice; @@ -194,22 +186,22 @@ static int sn_topology_show(struct seq_file *s, void *d) obj->name[i] = '_'; } - brickname = sn_hwperf_get_brickname(obj, objs, &ordinal); - seq_printf(s, "%s %d %s %s asic %s", brickname, ordinal, obj->location, + slabname = sn_hwperf_get_slabname(obj, objs, &ordinal); + seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, obj->sn_hwp_this_part ? "local" : "shared", obj->name); - if (obj->location[3] != 'c') + if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) seq_putc(s, '\n'); else { seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal)); - for (i=0; i < numnodes; i++) { + for (i=0; i < numionodes; i++) { seq_printf(s, i ? ":%d" : ", dist %d", node_distance(ordinal, i)); } seq_putc(s, '\n'); /* - * CPUs on this node + * CPUs on this node, if any */ cpumask = node_to_cpumask(ordinal); for_each_online_cpu(i) { @@ -253,11 +245,16 @@ static int sn_topology_show(struct seq_file *s, void *d) break; } } - if (i >= sn_hwperf_obj_cnt) - continue; seq_printf(s, "numalink %d %s-%d", ordinal+pt, obj->location, ptdata[pt].port); + if (i >= sn_hwperf_obj_cnt) { + /* no connection */ + seq_puts(s, " local endpoint disconnected" + ", protocol unknown\n"); + continue; + } + if (obj->sn_hwp_this_part && p->sn_hwp_this_part) /* both ends local to this partition */ seq_puts(s, " local"); @@ -276,9 +273,8 @@ static int sn_topology_show(struct seq_file *s, void *d) */ seq_printf(s, " endpoint %s-%d, protocol %s\n", p->location, ptdata[pt].conn_port, - strcmp(obj->name, "NL3Router") == 0 || - strcmp(p->name, "NL3Router") == 0 ? - "LLP3" : "LLP4"); + (SN_HWPERF_IS_NL3ROUTER(obj) || + SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4"); } vfree(ptdata); } @@ -378,6 +374,42 @@ out: return r; } +/* map SAL hwperf error code to system error code */ +static int sn_hwperf_map_err(int hwperf_err) +{ + int e; + + switch(hwperf_err) { + case SN_HWPERF_OP_OK: + e = 0; + break; + + case SN_HWPERF_OP_NOMEM: + e = -ENOMEM; + break; + + case SN_HWPERF_OP_NO_PERM: + e = -EPERM; + break; + + case SN_HWPERF_OP_IO_ERROR: + e = -EIO; + break; + + case SN_HWPERF_OP_BUSY: + case SN_HWPERF_OP_RECONFIGURE: + e = -EAGAIN; + break; + + case SN_HWPERF_OP_INVAL: + default: + e = -EINVAL; + break; + } + + return e; +} + /* * ioctl for "sn_hwperf" misc device */ @@ -405,7 +437,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) r = -EINVAL; goto error; } - r = copy_from_user(&a, (const void *)arg, + r = copy_from_user(&a, (const void __user *)arg, sizeof(struct sn_hwperf_ioctl_args)); if (r != 0) { r = -EFAULT; @@ -426,7 +458,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) } if (op & SN_HWPERF_OP_MEM_COPYIN) { - r = copy_from_user(p, (const void *)a.ptr, a.sz); + r = copy_from_user(p, (const void __user *)a.ptr, a.sz); if (r != 0) { r = -EFAULT; goto error; @@ -473,7 +505,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) case SN_HWPERF_GET_NODE_NASID: if (a.sz != sizeof(u64) || - (node = a.arg) < 0 || node >= numnodes) { + (node = a.arg) < 0 || node >= numionodes) { r = -EINVAL; goto error; } @@ -515,18 +547,26 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) op_info.v0 = &v0; op_info.op = op; r = sn_hwperf_op_cpu(&op_info); + if (r) { + r = sn_hwperf_map_err(r); + goto error; + } break; default: /* all other ops are a direct SAL call */ r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op, a.arg, a.sz, (u64) p, 0, 0, &v0); + if (r) { + r = sn_hwperf_map_err(r); + goto error; + } a.v0 = v0; break; } if (op & SN_HWPERF_OP_MEM_COPYOUT) { - r = copy_to_user((void *)a.ptr, p, a.sz); + r = copy_to_user((void __user *)a.ptr, p, a.sz); if (r != 0) { r = -EFAULT; goto error; @@ -534,8 +574,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) } error: - if (p) - vfree(p); + vfree(p); lock_kernel(); return r; @@ -646,7 +685,6 @@ int sn_topology_release(struct inode *inode, struct file *file) { struct seq_file *seq = file->private_data; - if (seq->private) - vfree(seq->private); + vfree(seq->private); return seq_release(inode, file); }