/* * prom_walk_devs() implements a generic walker for the OBP tree; this * implementation uses an explicitly managed stack in order to save the * overhead of a recursive implementation. */ void prom_walk_devs(pnode_t node, int (*cb)(pnode_t, void *, void *), void *arg, void *result) { pnode_t stack[OBP_STACKDEPTH]; int stackidx = 0; if (node == OBP_NONODE || node == OBP_BADNODE) { prom_panic("Invalid node specified as root of prom tree walk"); } stack[0] = node; for (;;) { pnode_t curnode = stack[stackidx]; pnode_t child; /* * We're out of stuff to do at this level, bump back up a level * in the tree, and move to the next node; if the new level * will be level -1, we're done. */ if (curnode == OBP_NONODE || curnode == OBP_BADNODE) { stackidx--; if (stackidx < 0) return; stack[stackidx] = prom_nextnode(stack[stackidx]); continue; } switch ((*cb)(curnode, arg, result)) { case PROM_WALK_TERMINATE: return; case PROM_WALK_CONTINUE: /* * If curnode has a child, traverse to it, * otherwise move to curnode's sibling. */ child = prom_childnode(curnode); if (child != OBP_NONODE && child != OBP_BADNODE) { stackidx++; stack[stackidx] = child; } else { stack[stackidx] = prom_nextnode(stack[stackidx]); } break; default: prom_panic("unrecognized walk directive"); } } }
int pxtool_dev_reg_ops_platchk(dev_info_t *dip, pcitool_reg_t *prg_p) { int devi_nodeid = ddi_get_nodeid(dip); /* * Guard against checking a root nexus which is empty. * On some systems this will result in a Fatal Reset. */ if ((int)prom_childnode((pnode_t)devi_nodeid) == OBP_NONODE) { DBG(DBG_TOOLS, dip, "pxtool_dev_reg_ops set/get reg: nexus has no devs!\n"); prg_p->status = PCITOOL_IO_ERROR; return (ENXIO); } return (SUCCESS); }
/* * Platform specific lgroup initialization */ void plat_lgrp_init(void) { pnode_t curnode; char tmp_name[MAXSYSNAME]; int portid; int cpucnt = 0; int max_portid = -1; extern uint32_t lgrp_expand_proc_thresh; extern uint32_t lgrp_expand_proc_diff; extern pgcnt_t lgrp_mem_free_thresh; extern uint32_t lgrp_loadavg_tolerance; extern uint32_t lgrp_loadavg_max_effect; extern uint32_t lgrp_load_thresh; extern lgrp_mem_policy_t lgrp_mem_policy_root; /* * Count the number of CPUs installed to determine if * NUMA optimization should be enabled or not. * * All CPU nodes reside in the root node and have a * device type "cpu". */ curnode = prom_rootnode(); for (curnode = prom_childnode(curnode); curnode; curnode = prom_nextnode(curnode)) { bzero(tmp_name, MAXSYSNAME); if (prom_getprop(curnode, OBP_NAME, (caddr_t)tmp_name) == -1 || prom_getprop(curnode, OBP_DEVICETYPE, tmp_name) == -1 || strcmp(tmp_name, "cpu") != 0) continue; cpucnt++; if (prom_getprop(curnode, "portid", (caddr_t)&portid) != -1 && portid > max_portid) max_portid = portid; } if (cpucnt <= 1) max_mem_nodes = 1; else if (max_portid >= 0 && max_portid < MAX_MEM_NODES) max_mem_nodes = max_portid + 1; /* * Set tuneables for fiesta architecture * * lgrp_expand_proc_thresh is the minimum load on the lgroups * this process is currently running on before considering * expanding threads to another lgroup. * * lgrp_expand_proc_diff determines how much less the remote lgroup * must be loaded before expanding to it. * * Optimize for memory bandwidth by spreading multi-threaded * program to different lgroups. */ lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1; lgrp_expand_proc_diff = lgrp_loadavg_max_effect / 2; lgrp_loadavg_tolerance = lgrp_loadavg_max_effect / 2; lgrp_mem_free_thresh = 1; /* home lgrp must have some memory */ lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1; lgrp_mem_policy_root = LGRP_MEM_POLICY_NEXT; lgrp_load_thresh = 0; mem_node_pfn_shift = ENCHILADA_MC_SHIFT - MMU_PAGESHIFT; }
/*ARGSUSED1*/ static int get_neighbors(dev_info_t *di, int flag) { register int nid, snid, cnid; dev_info_t *parent; char buf[OBP_MAXPROPNAME]; if (di == NULL) return (DDI_WALK_CONTINUE); nid = ddi_get_nodeid(di); snid = cnid = 0; switch (flag) { case DDI_WALK_PRUNESIB: cnid = (int)prom_childnode((pnode_t)nid); break; case DDI_WALK_PRUNECHILD: snid = (int)prom_nextnode((pnode_t)nid); break; case 0: snid = (int)prom_nextnode((pnode_t)nid); cnid = (int)prom_childnode((pnode_t)nid); break; default: return (DDI_WALK_TERMINATE); } if (snid && (snid != -1) && ((parent = ddi_get_parent(di)) != NULL)) { /* * add the first sibling that passes check_status() */ for (; snid && (snid != -1); snid = (int)prom_nextnode((pnode_t)snid)) { if (getlongprop_buf(snid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(snid, buf, parent) == DDI_SUCCESS) { (void) ddi_add_child(parent, buf, snid, -1); break; } } } } if (cnid && (cnid != -1)) { /* * add the first child that passes check_status() */ if (getlongprop_buf(cnid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(cnid, buf, di) == DDI_SUCCESS) { (void) ddi_add_child(di, buf, cnid, -1); } else { for (cnid = (int)prom_nextnode((pnode_t)cnid); cnid && (cnid != -1); cnid = (int)prom_nextnode((pnode_t)cnid)) { if (getlongprop_buf(cnid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(cnid, buf, di) == DDI_SUCCESS) { (void) ddi_add_child( di, buf, cnid, -1); break; } } } } } } return (DDI_WALK_CONTINUE); }