void pcibr_hints_subdevs(devfs_handle_t xconn_vhdl, pciio_slot_t slot, uint64_t subdevs) { arbitrary_info_t ainfo = 0; char sdname[16]; devfs_handle_t pconn_vhdl = GRAPH_VERTEX_NONE; sprintf(sdname, "pci/%d", slot); (void) hwgraph_path_add(xconn_vhdl, sdname, &pconn_vhdl); if (pconn_vhdl == GRAPH_VERTEX_NONE) { #if DEBUG printk("pcibr_hints_subdevs: hwgraph_path_create failed at\n" "\t%p (seeking %s)\n", xconn_vhdl, sdname); #endif return; } hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); if (ainfo == 0) { uint64_t *subdevp; NEW(subdevp); if (!subdevp) { #if DEBUG printk("pcibr_hints_subdevs: subdev ptr alloc failed at\n" "\t%p\n", pconn_vhdl); #endif return; } *subdevp = subdevs; hwgraph_info_add_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, (arbitrary_info_t) subdevp); hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); if (ainfo == (arbitrary_info_t) subdevp) return; DEL(subdevp); if (ainfo == (arbitrary_info_t) NULL) { #if DEBUG printk("pcibr_hints_subdevs: null subdevs ptr at\n" "\t%p\n", pconn_vhdl); #endif return; } #if DEBUG printk("pcibr_subdevs_get: dup subdev add_LBL at\n" "\t%p\n", pconn_vhdl); #endif } *(uint64_t *) ainfo = subdevs; }
/* ARGSUSED */ static void volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) { xswitch_vol_t xvolinfo = NULL; devfs_handle_t hubv; hubinfo_t hubinfo; (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { return; } mutex_lock(&xvolinfo->xswitch_volunteer_mutex); ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; xvolinfo->xswitch_volunteer_count++; /* * if dual ported, make the lowest widgetid always be * xswitch_volunteer[0]. */ if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) { hubv = xvolinfo->xswitch_volunteer[0]; hubinfo_get(hubv, &hubinfo); if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) { xvolinfo->xswitch_volunteer[0] = xvolinfo->xswitch_volunteer[1]; xvolinfo->xswitch_volunteer[1] = hubv; } } mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); }
/* ARGSUSED */ static void volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) { xswitch_vol_t xvolinfo = NULL; (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { #ifdef LATER if (!is_headless_node_vertex(master)) { #if defined(SUPPORT_PRINTING_V_FORMAT) printk(KERN_WARNING "volunteer for widgets: vertex %v has no info label", xswitch); #else printk(KERN_WARNING "volunteer for widgets: vertex 0x%x has no info label", xswitch); #endif } #endif /* LATER */ return; } mutex_lock(&xvolinfo->xswitch_volunteer_mutex); ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; xvolinfo->xswitch_volunteer_count++; mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); }
/* * Obtain a pointer to the pciio_provider functions for a specified Crosstalk * provider. */ pciio_provider_t * pciio_provider_fns_get(devfs_handle_t provider) { arbitrary_info_t ainfo = 0; (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo); return (pciio_provider_t *) ainfo; }
pciio_info_t pciio_info_chk(devfs_handle_t pciio) { arbitrary_info_t ainfo = 0; hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo); return (pciio_info_t) ainfo; }
/* xwidget_info_chk: * check to see if this vertex is a widget; * if so, return its widget_info (if any). * if not, return NULL. */ xwidget_info_t xwidget_info_chk(vertex_hdl_t xwidget) { arbitrary_info_t ainfo = 0; hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo); return (xwidget_info_t) ainfo; }
pciio_info_t pciio_info_chk(vertex_hdl_t pciio) { arbitrary_info_t ainfo = 0; hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo); return (pciio_info_t) ainfo; }
/* * copy xwidget_info_t from conn_v to peer_conn_v */ static int pic_bus1_widget_info_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v, cnodeid_t xbow_peer, char *peer_path) { xwidget_info_t widget_info, peer_widget_info; vertex_hdl_t peer_hubv; hubinfo_t peer_hub_info; /* get the peer hub's widgetid */ peer_hubv = NODEPDA(xbow_peer)->node_vertex; peer_hub_info = NULL; hubinfo_get(peer_hubv, &peer_hub_info); if (peer_hub_info == NULL) return 0; if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) { peer_widget_info = kmalloc(sizeof (*(peer_widget_info)), GFP_KERNEL); if ( !peer_widget_info ) { return -ENOMEM; } memset(peer_widget_info, 0, sizeof (*(peer_widget_info))); peer_widget_info->w_fingerprint = widget_info_fingerprint; peer_widget_info->w_vertex = peer_conn_v; peer_widget_info->w_id = widget_info->w_id; peer_widget_info->w_master = peer_hubv; peer_widget_info->w_masterid = peer_hub_info->h_widgetid; /* structure copy */ peer_widget_info->w_hwid = widget_info->w_hwid; peer_widget_info->w_efunc = 0; peer_widget_info->w_einfo = 0; peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); if (!peer_widget_info->w_name) { kfree(peer_widget_info); return -ENOMEM; } strcpy(peer_widget_info->w_name, peer_path); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { kfree(peer_widget_info->w_name); kfree(peer_widget_info); return 0; } xwidget_info_set(peer_conn_v, peer_widget_info); return 1; } printk("pic_bus1_widget_info_dup: " "cannot get INFO_LBL_XWIDGET from 0x%lx\n", (uint64_t)conn_v); return 0; }
void pcibr_hints_subdevs(devfs_handle_t xconn_vhdl, pciio_slot_t slot, uint64_t subdevs) { arbitrary_info_t ainfo = 0; char sdname[16]; devfs_handle_t pconn_vhdl = GRAPH_VERTEX_NONE; sprintf(sdname, "%s/%d", EDGE_LBL_PCI, slot); (void) hwgraph_path_add(xconn_vhdl, sdname, &pconn_vhdl); if (pconn_vhdl == GRAPH_VERTEX_NONE) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_hints_subdevs: hwgraph_path_create failed\n")); return; } hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); if (ainfo == 0) { uint64_t *subdevp; NEW(subdevp); if (!subdevp) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_hints_subdevs: subdev ptr alloc failed\n")); return; } *subdevp = subdevs; hwgraph_info_add_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, (arbitrary_info_t) subdevp); hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); if (ainfo == (arbitrary_info_t) subdevp) return; DEL(subdevp); if (ainfo == (arbitrary_info_t) NULL) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_hints_subdevs: null subdevs ptr\n")); return; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_subdevs_get: dup subdev add_LBL\n")); } *(uint64_t *) ainfo = subdevs; }
pcibr_hints_t pcibr_hints_get(devfs_handle_t xconn_vhdl, int alloc) { arbitrary_info_t ainfo = 0; graph_error_t rv; pcibr_hints_t hint; rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo); if (alloc && (rv != GRAPH_SUCCESS)) { NEW(hint); hint->rrb_alloc_funct = NULL; hint->ph_intr_bits = NULL; rv = hwgraph_info_add_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, (arbitrary_info_t) hint); if (rv != GRAPH_SUCCESS) goto abnormal_exit; rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo); if (rv != GRAPH_SUCCESS) goto abnormal_exit; if (ainfo != (arbitrary_info_t) hint) goto abnormal_exit; } return (pcibr_hints_t) ainfo; abnormal_exit: #ifdef LATER printf("SHOULD NOT BE HERE\n"); #endif DEL(hint); return(NULL); }
/* * copy xwidget_info_t from conn_v to peer_conn_v */ int pic_bus1_widget_info_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v, cnodeid_t xbow_peer) { xwidget_info_t widget_info, peer_widget_info; char peer_path[256]; vertex_hdl_t peer_hubv; hubinfo_t peer_hub_info; /* get the peer hub's widgetid */ peer_hubv = NODEPDA(xbow_peer)->node_vertex; peer_hub_info = NULL; hubinfo_get(peer_hubv, &peer_hub_info); if (peer_hub_info == NULL) return 0; if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) { NEW(peer_widget_info); peer_widget_info->w_vertex = peer_conn_v; peer_widget_info->w_id = widget_info->w_id; peer_widget_info->w_master = peer_hubv; peer_widget_info->w_masterid = peer_hub_info->h_widgetid; /* structure copy */ peer_widget_info->w_hwid = widget_info->w_hwid; peer_widget_info->w_efunc = 0; peer_widget_info->w_einfo = 0; peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); strcpy(peer_widget_info->w_name, peer_path); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { DEL(peer_widget_info); return 0; } xwidget_info_set(peer_conn_v, peer_widget_info); return 1; } printk("pic_bus1_widget_info_dup: " "cannot get INFO_LBL_XWIDGET from 0x%lx\n", (uint64_t)conn_v); return 0; }
device_desc_t device_desc_default_get(devfs_handle_t dev) { #ifdef LATER graph_error_t rc; device_desc_t device_desc; rc = hwgraph_info_get_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t *)&device_desc); if (rc == GRAPH_SUCCESS) return(device_desc); else return(NULL); #else FIXME("device_desc_default_get"); return((device_desc_t)0); #endif }
/* * copy inventory_t from conn_v to peer_conn_v */ int pic_bus1_inventory_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v) { inventory_t *pinv, *peer_pinv; if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT, (arbitrary_info_t *)&pinv) == GRAPH_SUCCESS) { NEW(peer_pinv); bcopy((const char *)pinv, (char *)peer_pinv, sizeof(inventory_t)); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT, (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) { DEL(peer_pinv); return 0; } return 1; } printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ", (uint64_t)conn_v); return 0; }
/* ARGSUSED */ static void volunteer_for_widgets(vertex_hdl_t xswitch, vertex_hdl_t master) { xswitch_vol_t xvolinfo = NULL; vertex_hdl_t hubv; hubinfo_t hubinfo; (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { if (!is_headless_node_vertex(master)) { char name[MAXDEVNAME]; printk(KERN_WARNING "volunteer for widgets: vertex %s has no info label", vertex_to_name(xswitch, name, MAXDEVNAME)); } return; } down(&xvolinfo->xswitch_volunteer_mutex); ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; xvolinfo->xswitch_volunteer_count++; /* * if dual ported, make the lowest widgetid always be * xswitch_volunteer[0]. */ if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) { hubv = xvolinfo->xswitch_volunteer[0]; hubinfo_get(hubv, &hubinfo); if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) { xvolinfo->xswitch_volunteer[0] = xvolinfo->xswitch_volunteer[1]; xvolinfo->xswitch_volunteer[1] = hubv; } } up(&xvolinfo->xswitch_volunteer_mutex); }
/* ARGSUSED */ static void assign_widgets_to_volunteers(vertex_hdl_t xswitch, vertex_hdl_t hubv) { xswitch_info_t xswitch_info; xswitch_vol_t xvolinfo = NULL; xwidgetnum_t widgetnum; int num_volunteer; nasid_t nasid; hubinfo_t hubinfo; extern int iobrick_type_get_nasid(nasid_t); hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; xswitch_info = xswitch_info_get(xswitch); ASSERT(xswitch_info != NULL); (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { if (!is_headless_node_vertex(hubv)) printk(KERN_WARNING "assign_widgets_to_volunteers:vertex 0x%p has " " no info label", (void *)xswitch); return; } num_volunteer = xvolinfo->xswitch_volunteer_count; ASSERT(num_volunteer > 0); /* Assign master hub for xswitch itself. */ if (HUB_WIDGET_ID_MIN > 0) { hubv = xvolinfo->xswitch_volunteer[0]; xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); } /* * TBD: Use administrative information to alter assignment of * widgets to hubs. */ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { int i; /* * Ignore disabled/empty ports. */ if (!xbow_port_io_enabled(nasid, widgetnum)) continue; /* * If this is the master IO board, assign it to the same * hub that owned it in the prom. */ if (is_master_baseio_nasid_widget(nasid, widgetnum)) { extern nasid_t snia_get_master_baseio_nasid(void); for (i=0; i<num_volunteer; i++) { hubv = xvolinfo->xswitch_volunteer[i]; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; if (nasid == snia_get_master_baseio_nasid()) goto do_assignment; } panic("Nasid == %d, console nasid == %d", nasid, snia_get_master_baseio_nasid()); } /* * Assuming that we're dual-hosted and that PCI cards * are naturally placed left-to-right, alternate PCI * buses across both Cbricks. For Pbricks, and Ibricks, * io_brick_map_widget() returns the PCI bus number * associated with the given brick type and widget number. * For Xbricks, it returns the XIO slot number. */ i = 0; if (num_volunteer > 1) { int bt; bt = iobrick_type_get_nasid(nasid); if (bt >= 0) { i = io_brick_map_widget(bt, widgetnum) & 1; } } hubv = xvolinfo->xswitch_volunteer[i]; do_assignment: /* * At this point, we want to make hubv the master of widgetnum. */ xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); } xswitch_volunteer_delete(xswitch); }
/* ARGSUSED */ static void assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) { xswitch_info_t xswitch_info; xswitch_vol_t xvolinfo = NULL; xwidgetnum_t widgetnum; int num_volunteer; nasid_t nasid; hubinfo_t hubinfo; extern int iobrick_type_get_nasid(nasid_t); hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; xswitch_info = xswitch_info_get(xswitch); ASSERT(xswitch_info != NULL); (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { return; } num_volunteer = xvolinfo->xswitch_volunteer_count; ASSERT(num_volunteer > 0); /* Assign master hub for xswitch itself. */ if (HUB_WIDGET_ID_MIN > 0) { hubv = xvolinfo->xswitch_volunteer[0]; xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); } /* * TBD: Use administrative information to alter assignment of * widgets to hubs. */ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { int i; /* * Ignore disabled/empty ports. */ if (!xbow_port_io_enabled(nasid, widgetnum)) continue; /* * If this is the master IO board, assign it to the same * hub that owned it in the prom. */ if (is_master_nasid_widget(nasid, widgetnum)) { for (i=0; i<num_volunteer; i++) { hubv = xvolinfo->xswitch_volunteer[i]; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; if (nasid == get_console_nasid()) goto do_assignment; } } /* * Assuming that we're dual-hosted and that PCI cards * are naturally placed left-to-right, alternate PCI * buses across both Cbricks. For Pbricks, and Ibricks, * io_brick_map_widget() returns the PCI bus number * associated with the given brick type and widget number. * For Xbricks, it returns the XIO slot number. */ i = 0; if (num_volunteer > 1) { int bt; bt = iobrick_type_get_nasid(nasid); if (bt >= 0) { /* * PXBRICK has two busses per widget so this * algorithm wouldn't work (all busses would * be assigned to one volunteer). Change the * bricktype to PBRICK whose mapping is setup * suchthat 2 of the PICs will be assigned to * one volunteer and the other one will be * assigned to the other volunteer. */ if (bt == MODULE_PXBRICK) bt = MODULE_PBRICK; i = io_brick_map_widget(bt, widgetnum) & 1; } } hubv = xvolinfo->xswitch_volunteer[i]; do_assignment: /* * At this point, we want to make hubv the master of widgetnum. */ xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); } xswitch_volunteer_delete(xswitch); }
/* ARGSUSED */ static void assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) { int curr_volunteer, num_volunteer; xwidgetnum_t widgetnum; xswitch_info_t xswitch_info; xswitch_vol_t xvolinfo = NULL; nasid_t nasid; hubinfo_t hubinfo; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; xswitch_info = xswitch_info_get(xswitch); ASSERT(xswitch_info != NULL); (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { #ifdef LATER if (!is_headless_node_vertex(hubv)) { #if defined(SUPPORT_PRINTING_V_FORMAT) printk(KERN_WARNING "assign_widgets_to_volunteers:vertex %v has " " no info label", xswitch); #else printk(KERN_WARNING "assign_widgets_to_volunteers:vertex 0x%x has " " no info label", xswitch); #endif } #endif /* LATER */ return; } num_volunteer = xvolinfo->xswitch_volunteer_count; ASSERT(num_volunteer > 0); curr_volunteer = 0; /* Assign master hub for xswitch itself. */ if (HUB_WIDGET_ID_MIN > 0) { hubv = xvolinfo->xswitch_volunteer[0]; xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); } /* * TBD: Use administrative information to alter assignment of * widgets to hubs. */ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { /* * Ignore disabled/empty ports. */ if (!xbow_port_io_enabled(nasid, widgetnum)) continue; /* * If this is the master IO board, assign it to the same * hub that owned it in the prom. */ if (is_master_nasid_widget(nasid, widgetnum)) { int i; for (i=0; i<num_volunteer; i++) { hubv = xvolinfo->xswitch_volunteer[i]; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; if (nasid == get_console_nasid()) goto do_assignment; } #ifdef LATER PRINT_PANIC("Nasid == %d, console nasid == %d", nasid, get_console_nasid()); #endif } /* * Do a round-robin assignment among the volunteer nodes. */ hubv = xvolinfo->xswitch_volunteer[curr_volunteer]; curr_volunteer = (curr_volunteer + 1) % num_volunteer; /* fall through */ do_assignment: /* * At this point, we want to make hubv the master of widgetnum. */ xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); } xswitch_volunteer_delete(xswitch); }