Ejemplo n.º 1
0
/* ARGSUSED */
static void __init
klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
{
        vertex_hdl_t my_cpu, cpu_dir;
        char name[120];
        cpuid_t cpu_id;
	nasid_t nasid;

	nasid = cnodeid_to_nasid(cnode);
        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);

        snprintf(name, 120, "%s/%d/%c",
                EDGE_LBL_CPUBUS,
                0,
                'a' + cpu->cpu_info.physid);

        (void) hwgraph_path_add(node_vertex, name, &my_cpu);

	HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n");

	mark_cpuvertex_as_cpu(my_cpu, cpu_id);
        device_master_set(my_cpu, node_vertex);

        /* Add an alias under the node's CPU directory */
        if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
                snprintf(name, 120, "%c", 'a' + cpu->cpu_info.physid);
                (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
		HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name);
        }
}
Ejemplo n.º 2
0
/*
 * hwgraph_path_add - Create a directory node with the given path starting 
 * from the given vertex_hdl_t.
 */
int
hwgraph_path_add(vertex_hdl_t  fromv,
		 char *path,
		 vertex_hdl_t *new_de)
{

	unsigned int	namelen = strlen(path);
	int		rv;

	/*
	 * We need to handle the case when fromv is NULL ..
	 * in this case we need to create the path from the 
	 * hwgraph root!
	 */
	if (fromv == NULL)
		fromv = hwgraph_root;

	/*
	 * check the entry doesn't already exist, if it does
	 * then we simply want new_de to point to it (otherwise
	 * we'll overwrite the existing labelcl_info struct)
	 */
	rv = hwgraph_edge_get(fromv, path, new_de);
	if (rv)	{	/* couldn't find entry so we create it */
		*new_de = hwgraph_mk_dir(fromv, path, namelen, NULL);
		if (new_de == NULL)
			return(-1);
		else
			return(0);
	}
	else 
 		return(0);

}
Ejemplo n.º 3
0
/*
** Return the "master" for a given vertex.  A master vertex is a
** controller or adapter or other piece of hardware that the given
** vertex passes through on the way to the rest of the system.
*/
devfs_handle_t
device_master_get(devfs_handle_t vhdl)
{
	graph_error_t rc;
	devfs_handle_t master;

	rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master);
	if (rc == GRAPH_SUCCESS)
		return(master);
	else
		return(GRAPH_VERTEX_NONE);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
/*
 * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure   
 *      initialization has completed to set up the mappings between Xbridge
 *      and logical pci bus numbers.  We also set up the NASID for each of these
 *      xbridges.
 *
 *      Must be called before pci_init() is invoked.
 */
int
pci_bus_to_hcl_cvlink(void) 
{

	devfs_handle_t devfs_hdl = NULL;
	devfs_handle_t xtalk = NULL;
	int rv = 0;
	char name[256];
	int master_iobrick;
	int i;

	/*
	 * Iterate throught each xtalk links in the system ..
	 * /hw/module/001c01/node/xtalk/ 8|9|10|11|12|13|14|15 
	 *
	 * /hw/module/001c01/node/xtalk/15 -> /hw/module/001c01/Ibrick/xtalk/15
	 *
	 * What if it is not pci?
	 */
	devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module");

	/*
	 * To provide consistent(not persistent) device naming, we need to start 
	 * bus number allocation from the C-Brick with the lowest module id e.g. 001c01 
	 * with an attached I-Brick.  Find the master_iobrick.
	 */
	master_iobrick = -1;
	for (i = 0; i < nummodules; i++) {
		moduleid_t iobrick_id; 
		iobrick_id = iobrick_module_get(&modules[i]->elsc);
		if (iobrick_id > 0) { /* Valid module id */
			if (MODULE_GET_BTYPE(iobrick_id) == MODULE_IBRICK) {
				master_iobrick = i;
				break;
			}
		}
	}

	/*
	 * The master_iobrick gets bus 0 and 1.
	 */
	if (master_iobrick >= 0) {
		memset(name, 0, 256);
		format_module_id(name, modules[master_iobrick]->id, MODULE_FORMAT_BRIEF);
		strcat(name, "/node/xtalk");
		xtalk = NULL;
		rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
		pci_bus_map_create(xtalk);
	}
		
	/*
	 * Now go do the rest of the modules, starting from the C-Brick with the lowest 
	 * module id, remembering to skip the master_iobrick, which was done above.
	 */
	for (i = 0; i < nummodules; i++) {
		if (i == master_iobrick) {
			continue; /* Did the master_iobrick already. */
		}

		memset(name, 0, 256);
		format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
		strcat(name, "/node/xtalk");
		xtalk = NULL;
		rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
		pci_bus_map_create(xtalk);
	}

	return(0);
}