/*ARGSUSED*/ int mem_refcnt_open(devfs_handle_t *devp, mode_t oflag, int otyp, cred_t *crp) { cnodeid_t node; #ifndef CONFIG_IA64_SGI_SN1 extern int numnodes; #endif ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(*devp) == HUBSPC_REFCOUNTERS ); if (!cap_able(CAP_MEMORY_MGT)) { return (EPERM); } node = master_node_get(*devp); ASSERT( (node >= 0) && (node < numnodes) ); if (NODEPDA(node)->migr_refcnt_counterbuffer == NULL) { return (ENODEV); } ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); ASSERT( NODEPDA(node)->migr_refcnt_cbsize != (size_t)0 ); return (0); }
/*ARGSUSED*/ int mem_refcnt_mmap(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) { cnodeid_t node; int errcode; char* buffer; size_t blen; #ifndef CONFIG_IA64_SGI_SN1 extern int numnodes; #endif ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS ); node = master_node_get(dev); ASSERT( (node >= 0) && (node < numnodes) ); ASSERT( NODEPDA(node)->migr_refcnt_counterbuffer != NULL); ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); ASSERT( NODEPDA(node)->migr_refcnt_cbsize != 0 ); /* * XXXX deal with prot's somewhere around here.... */ buffer = NODEPDA(node)->migr_refcnt_counterbuffer; blen = NODEPDA(node)->migr_refcnt_cbsize; /* * Force offset to be a multiple of sizeof(refcnt_t) * We round up. */ off = (((off - 1)/sizeof(refcnt_t)) + 1) * sizeof(refcnt_t); if ( ((buffer + blen) - (buffer + off + len)) < 0 ) { return (EPERM); } errcode = v_mapphys(vt, buffer + off, len); return errcode; }
cpuid_t intr_heuristic(vertex_hdl_t dev, device_desc_t dev_desc, int req_bit, int resflags, vertex_hdl_t owner_dev, char *name, int *resp_bit) { cpuid_t cpuid; cpuid_t candidate = CPU_NONE; cnodeid_t candidate_node; vertex_hdl_t pconn_vhdl; pcibr_soft_t pcibr_soft; int bit; static cnodeid_t last_node = 0; /* SN2 + pcibr addressing limitation */ /* Due to this limitation, all interrupts from a given bridge must go to the name node.*/ /* The interrupt must also be targetted for the same processor. */ /* This limitation does not exist on PIC. */ /* But, the processor limitation will stay. The limitation will be similar to */ /* the bedrock/xbridge limit regarding PI's */ if ( (hwgraph_edge_get(dev, EDGE_LBL_PCI, &pconn_vhdl) == GRAPH_SUCCESS) && ( (pcibr_soft = pcibr_soft_get(pconn_vhdl) ) != NULL) ) { if (pcibr_soft->bsi_err_intr) { candidate = ((hub_intr_t)pcibr_soft->bsi_err_intr)->i_cpuid; } } if (candidate != CPU_NONE) { // The cpu was chosen already when we assigned the error interrupt. bit = intr_reserve_level(candidate, req_bit, resflags, owner_dev, name); if (bit < 0) { cpuid = CPU_NONE; } else { cpuid = candidate; *resp_bit = bit; } } else { // Need to choose one. Try the controlling c-brick first. cpuid = intr_bit_reserve_test(CPU_NONE, 0, master_node_get(dev), req_bit, 0, owner_dev, name, resp_bit); } if (cpuid != CPU_NONE) { return cpuid; } if (candidate != CPU_NONE) { printk("Cannot target interrupt to target node (%ld).\n",candidate); return CPU_NONE; } else { printk("Cannot target interrupt to closest node (0x%x) 0x%p\n", master_node_get(dev), (void *)owner_dev); } // We couldn't put it on the closest node. Try to find another one. // Do a stupid round-robin assignment of the node. { int i; if (last_node >= numnodes) last_node = 0; for (i = 0, candidate_node = last_node; i < numnodes; candidate_node++,i++) { if (candidate_node == numnodes) candidate_node = 0; cpuid = intr_bit_reserve_test(CPU_NONE, 0, candidate_node, req_bit, 0, owner_dev, name, resp_bit); if (cpuid != CPU_NONE) { last_node = candidate_node + 1; return cpuid; } } } printk("cannot target interrupt: 0x%p\n",(void *)owner_dev); return CPU_NONE; }
/* Define the system critical vertices and connect them through * a canonical parent-child relationships for easy traversal * during io error handling. */ static void sys_critical_graph_init(void) { devfs_handle_t bridge_vhdl,master_node_vhdl; devfs_handle_t xbow_vhdl = GRAPH_VERTEX_NONE; extern devfs_handle_t hwgraph_root; devfs_handle_t pci_slot_conn; int slot; devfs_handle_t baseio_console_conn; DBG("sys_critical_graph_init: FIXME.\n"); baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl); if (baseio_console_conn == NULL) { return; } /* Get the vertex handle for the baseio bridge */ bridge_vhdl = device_master_get(baseio_console_conn); /* Get the master node of the baseio card */ master_node_vhdl = cnodeid_to_vertex( master_node_get(baseio_console_vhdl)); /* Add the "root->node" part of the system critical graph */ sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl); /* Check if we have a crossbow */ if (hwgraph_traverse(master_node_vhdl, EDGE_LBL_XTALK"/0", &xbow_vhdl) == GRAPH_SUCCESS) { /* We have a crossbow.Add "node->xbow" part of the system * critical graph. */ sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl); /* Add "xbow->baseio bridge" of the system critical graph */ sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl); hwgraph_vertex_unref(xbow_vhdl); } else /* We donot have a crossbow. Add "node->baseio_bridge" * part of the system critical graph. */ sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl); /* Add all the populated PCI slot vertices to the system critical * graph with the bridge vertex as the parent. */ for (slot = 0 ; slot < 8; slot++) { char slot_edge[10]; sprintf(slot_edge,"%d",slot); if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn) != GRAPH_SUCCESS) continue; sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn); hwgraph_vertex_unref(pci_slot_conn); } hwgraph_vertex_unref(bridge_vhdl); /* Add the "ioc3 pci connection point -> console ioc3" part * of the system critical graph */ if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) == GRAPH_SUCCESS) { sys_critical_graph_vertex_add(pci_slot_conn, baseio_console_vhdl); hwgraph_vertex_unref(pci_slot_conn); } /* Add the "ethernet pci connection point -> base ethernet" part of * the system critical graph */ if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) == GRAPH_SUCCESS) { sys_critical_graph_vertex_add(pci_slot_conn, baseio_enet_vhdl); hwgraph_vertex_unref(pci_slot_conn); } /* Add the "scsi controller pci connection point -> base scsi * controller" part of the system critical graph */ if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0], "../..",&pci_slot_conn) == GRAPH_SUCCESS) { sys_critical_graph_vertex_add(pci_slot_conn, base_io_scsi_ctlr_vhdl[0]); hwgraph_vertex_unref(pci_slot_conn); } if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1], "../..",&pci_slot_conn) == GRAPH_SUCCESS) { sys_critical_graph_vertex_add(pci_slot_conn, base_io_scsi_ctlr_vhdl[1]); hwgraph_vertex_unref(pci_slot_conn); } hwgraph_vertex_unref(baseio_console_conn); }
/* ARGSUSED */ int mem_refcnt_ioctl(devfs_handle_t dev, int cmd, void *arg, int mode, cred_t *cred_p, int *rvalp) { cnodeid_t node; int errcode; extern int numnodes; ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS ); node = master_node_get(dev); ASSERT( (node >= 0) && (node < numnodes) ); ASSERT( NODEPDA(node)->migr_refcnt_counterbuffer != NULL); ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); ASSERT( NODEPDA(node)->migr_refcnt_cbsize != 0 ); errcode = 0; switch (cmd) { case RCB_INFO_GET: { rcb_info_t rcb; rcb.rcb_len = NODEPDA(node)->migr_refcnt_cbsize; rcb.rcb_sw_sets = NODEPDA(node)->migr_refcnt_numsets; rcb.rcb_sw_counters_per_set = numnodes; rcb.rcb_sw_counter_size = sizeof(refcnt_t); rcb.rcb_base_pages = NODEPDA(node)->migr_refcnt_numsets / NUM_OF_HW_PAGES_PER_SW_PAGE(); rcb.rcb_base_page_size = NBPP; rcb.rcb_base_paddr = ctob(slot_getbasepfn(node, 0)); rcb.rcb_cnodeid = node; rcb.rcb_granularity = MD_PAGE_SIZE; #ifdef notyet rcb.rcb_hw_counter_max = MIGR_COUNTER_MAX_GET(node); rcb.rcb_diff_threshold = MIGR_THRESHOLD_DIFF_GET(node); #endif rcb.rcb_abs_threshold = MIGR_THRESHOLD_ABS_GET(node); rcb.rcb_num_slots = node_getnumslots(node); if (COPYOUT(&rcb, arg, sizeof(rcb_info_t))) { errcode = EFAULT; } break; } case RCB_SLOT_GET: { rcb_slot_t slot[MAX_MEM_SLOTS]; int s; int nslots; nslots = node_getnumslots(node); ASSERT(nslots <= MAX_MEM_SLOTS); for (s = 0; s < nslots; s++) { slot[s].base = (uint64_t)ctob(slot_getbasepfn(node, s)); #ifdef notyet slot[s].size = (uint64_t)ctob(slot_getsize(node, s)); #else slot[s].size = (uint64_t)1; #endif } if (COPYOUT(&slot[0], arg, nslots * sizeof(rcb_slot_t))) { errcode = EFAULT; } *rvalp = nslots; break; } default: errcode = EINVAL; break; } return errcode; }