Ejemplo n.º 1
0
/**
 * add_pci_vio_node
 * @bried Add a PCI or virtual device node
 *
 * @param path ofdt path to this node
 * @param dev_type type of device
 * @param node_list pointer to list to add node to
 * @returns 0 on success, !0 otherwise
 */
static int
add_pci_vio_node(const char *path, int dev_type, struct dr_node **node_list)
{
	struct dr_connector *drc_list;
	struct dr_connector *drc;
	struct dr_node *node;
	int child_dev_type = 0;
	int rc = -1;

	drc_list = get_drc_info(path);
	if (drc_list == NULL)
		return -1;

	for (drc = drc_list; drc != NULL; drc = drc->next) {
		switch (dev_type) {
			case PCI_HP_DEV:
				if (! is_hp_type(drc->type))
					continue;
				child_dev_type = dev_type;
				break;

			case PCI_DLPAR_DEV:
			case VIO_DEV:
				if (! is_logical_type(drc->type))
					continue;
				child_dev_type = dev_type;
				break;
			case PHB_DEV:
				if (is_logical_type(drc->type))
					child_dev_type = PCI_DLPAR_DEV;
				else
					child_dev_type = PCI_HP_DEV;
				break;
		}

		node = alloc_dr_node(drc, child_dev_type, path);
		if (node == NULL) {
			say(ERROR, "Could not allocate pci/vio node\n");
			return -1;
		}

		if (child_dev_type == PCI_HP_DEV)
			node->is_owned = 1;

		rc = init_node(node);
		if (rc) {
			free(node);
			return rc;
		}

		node->next = *node_list;
		*node_list = node;
	}

	return rc;
}
Ejemplo n.º 2
0
/**
 * add_hea_node
 * @brief Add a node for an HEA adapter
 *
 * @param path ofdt_path to this node
 * @param drc_list list of drc's at OFDT_BASE
 * @param pointer to the node list to add new nodes to
 * @return 0 on success, !0 otherwise
 */
static int
add_hea_node(char *path, struct dr_connector *drc_list,
	     struct dr_node **node_list)
{
	struct dr_connector *drc;
	struct dr_node *hea_node;
	uint my_drc_index;
	int rc;

	if (drc_list == NULL)
		return -1;

	if (get_my_drc_index(path, &my_drc_index))
		return -1;

	for (drc = drc_list; drc != NULL; drc = drc->next) {
		if (drc->index == my_drc_index)
			break;
	}

	if (drc == NULL) {
		say(ERROR, "Could not find drc index 0x%x to add to hea list\n",
		    my_drc_index);
		return -1;
	}

	hea_node = alloc_dr_node(drc, HEA_DEV, path);
	if (hea_node == NULL) {
		say(ERROR, "Could not allocate hea node for drc index 0x%x\n",
		    my_drc_index);
		return -1;
	}

	hea_node->is_owned = 1;
	rc = init_node(hea_node);
	if (rc) {
		free(hea_node);
		return -1;
	}

	hea_node->next = *node_list;
	*node_list = hea_node;
	return 0;
}
Ejemplo n.º 3
0
/**
 * add_phb_node
 * @brief Add a PHB node to the node list
 *
 * @param ofdt_poath, ofdt path to this node
 * @param drc_list list of drc's at OFDT_BASE
 * @param node_list list of nodes to add node to
 * @returns 0 on success, !0 otherwise
 */
static int
add_phb_node(char *ofdt_path, struct dr_connector *drc_list,
	     struct dr_node **node_list)
{
	struct dr_node *phb_node;
	struct dr_connector *drc;
	uint my_drc_index;

	if (get_my_drc_index(ofdt_path, &my_drc_index))
		return -1;

	for (drc = drc_list; drc; drc = drc->next) {
		if (drc->index == my_drc_index)
			break;
	}

	if (drc == NULL) {
		say(ERROR, "Could not find drc index 0x%x to add to phb list\n",
		    my_drc_index);
		return -1;
	}

	phb_node = alloc_dr_node(drc, PHB_DEV, ofdt_path);
	if (phb_node == NULL) {
		say(ERROR, "Could not allocate PHB node for drc index 0x%x\n",
		    my_drc_index);
		return -1;
	}

	phb_node->is_owned = 1;

	add_pci_vio_node(ofdt_path, PHB_DEV, &phb_node->children);

	phb_node->next = *node_list;
	*node_list = phb_node;
	return 0;
}
Ejemplo n.º 4
0
/**
 * add_child_node
 *
 * Create information about the Open Firmware node and
 * add that information to the appropriate per-node list of
 * Open Firmware nodes. Also create the corresponding information
 * for any PCI device.
 *
 * NOTES:
 *	1) does not need to be concerned about one or more Open
 *	   Firmware nodes having the used-by-rtas property present.
 *	   One of the RTAS services used during removing a PCI adapter
 *	   must take the appropriate action (most likely eliminate RTAS
 *	   usage) in this case.
 *	2) Open Firmware node RPA physical location code:
 *
 *	  [Un.m-]Pn[-Pm]-In[[/Zn]-An]
 *
 *	  where
 *		Un.m is for the enclosure for multi-enclosue systems
 *		Pn is for the planar
 *		In is for the slot
 *		/Zn is for the connector on the adapter card
 *		An is for the device connected to the adapter
 *
 *	  note
 *		There may be multiple levels of planars [Pm].
 *
 * RECOVERY OPERATION:
 *	1) This function does not add the Open Firmware node if the user
 *	   mode process has exceeded all available malloc space. This
 *	   should not happen based on the rather small total amount of
 *	   memory allocation required. The node is marked as skip.
 *	2) This function does not add the device information if there
 *	   is a problem initializing device. The node is marked as skip.
 *
 * @param parent
 * @param child_path
 */
static void
add_child_node(struct dr_node *parent, char *child_path)
{
	struct dr_connector *drc_list, *drc;
	char loc_code[DR_BUF_SZ];
	char *slash;
	struct dr_node *child;
	uint my_drc_index;
	int rc;

	assert(parent != NULL);
	assert(strlen(child_path) != 0);

	/* Make sure that the Open Firmware node is not added twice
	 * in case the ibm,my-drc-index property is put in all nodes
	 * for the adapter instead of just the ones at the connector.
	 */
	if (parent->children != NULL) {
		struct dr_node *tmp;
		for (tmp = parent->children; tmp; tmp = tmp->next) {
			if (! strcmp(tmp->ofdt_path, child_path))
				return;
		}
	}

	/* Create the Open Firmware node's information and insert that
	 * information into the node's list based on the node's RPA
	 * physical location code.  Ignore the OF node if the node
	 * does not have an RPA physical location code because that is
	 * a firmware error.
	 */
	rc = get_property(child_path, "ibm,loc-code", &loc_code, DR_BUF_SZ);
	if (rc)
		return;

	/* Skip the Open Firmware node if it is a device node. Determine that
	 * the node is for a device by looking for a hyphen after the last
	 * slash (...-In/Z1-An).
	 */
	slash = strrchr(loc_code, '/');
	if (slash != NULL) {
		char *hyphen;
		hyphen = strchr(slash, '-');
		if (hyphen != NULL)
			return;

		*slash = '\0';
	}

	if (parent->dev_type == PCI_HP_DEV) { 	/* hotplug */
		/* Squadrons don't have "/" in devices' (scsi,
		 * ethernet, tokenring ...) loc-code strings.
		 *
		 * Skip the Open Firmware node if the node's RPA
		 * physical location code does not match the node's
		 * location code.  Ignore the connector information,
		 * i.e. information after last slash if no hyphen
		 * follows.
		 */
		if ((strcmp(parent->drc_name, loc_code) != 0)
		    && (slash != NULL)) {
			parent->skip = 1;
			return;
		}
	}

	/* Restore the slash because the full RPA location code
	 * is saved for each OF node so that the connector
	 * information can be used to sort the OF node list for
	 * each node.
	 */
	if (slash != NULL)
		*slash = '/';

	if (get_my_drc_index(child_path, &my_drc_index))
		return;

	/* need the drc-info in the dir above */
	slash = strrchr(child_path, '/');
	*slash = '\0';
	drc_list = get_drc_info(child_path);
	*slash = '/';

	for (drc = drc_list; drc != NULL; drc = drc->next) {
		if (drc->index == my_drc_index)
			break;
	}

	/* Allocate space for the Open Firmware node information.  */
	child = alloc_dr_node(drc, parent->dev_type, child_path);
	if (child == NULL) {
		parent->skip = 1;
		return;
	}

	if ((! strcmp(parent->drc_type, "SLOT"))
	    && (parent->dev_type == PCI_DLPAR_DEV))
		snprintf(child->ofdt_dname, DR_STR_MAX, "%s",
			 parent->ofdt_dname);
	else
		get_property(child_path, "name", child->ofdt_dname,
			     sizeof(child->ofdt_dname));

	switch (parent->dev_type) {
	    case PCI_HP_DEV:
	    case PCI_DLPAR_DEV:
	    {
		get_ofdt_uint_property(child_path, "vendor-id",
				       &child->pci_vendor_id);
		get_ofdt_uint_property(child_path, "device-id",
				       &child->pci_device_id);
		get_ofdt_uint_property(child_path, "class_code",
				       &child->pci_class_code);
		break;
	    }

	    case HEA_DEV:
	    {
		child->dev_type = HEA_PORT_DEV;

		get_ofdt_uint_property(child_path, "ibm,hea-port-no",
				       &child->hea_port_no);
		get_ofdt_uint_property(child_path, "ibm,hea-port-tenure",
				       &child->hea_port_tenure);
		break;
	    }
	}

	child->next = parent->children;
	parent->children = child;
}
Ejemplo n.º 5
0
/**
 * init_cpu_info
 * @brief Initialize cpu information
 *
 * @returns pointer to cpu_info on success, NULL otherwise
 */
static int
init_cpu_info(struct dr_info *dr_info)
{
	struct dr_connector *drc_list, *drc;
	struct dr_node *cpu, *cpu_list = NULL;
	DIR *d;
	struct dirent *de;
	int rc = 0;

	drc_list = get_drc_info(CPU_OFDT_BASE);
	if (drc_list == NULL) {
		say(ERROR, "Could not get drc information for %s\n",
		    CPU_OFDT_BASE);
		return -1;
	}

	/* For cpu dlpar, we need a list of all possible cpus on the system */
	for (drc = drc_list; drc; drc = drc->next) {
		cpu = alloc_dr_node(drc, CPU_DEV, NULL);
		if (cpu == NULL) {
			say(ERROR, "Could not allocate CPU node structure: "
			    "%s\n", strerror(errno));
			free_node(cpu_list);
			return -1;
		}

		cpu->next = cpu_list;
		cpu_list = cpu;
	}

	d = opendir(CPU_OFDT_BASE);
	if (d == NULL) {
		say(ERROR, "Could not open %s: %s\n", CPU_OFDT_BASE,
		    strerror(errno));
		free_node(cpu_list);
		return -1;
	}

	while ((de = readdir(d)) != NULL) {
		char path[DR_PATH_MAX];

		if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name))
			continue;

		if (! strncmp(de->d_name, "PowerPC", 7)) {
			uint32_t my_drc_index;

			memset(path, 0, 1024);
			sprintf(path, "%s/%s", CPU_OFDT_BASE, de->d_name);

			rc = get_my_drc_index(path, &my_drc_index);
			if (rc) {
				say(ERROR, "Could not retrieve drc index for "
				    "%s\n", path);
				break;
			}

			for (cpu = cpu_list; cpu; cpu = cpu->next) {
				if (cpu->drc_index == my_drc_index)
					break;
			}

			if (cpu == NULL) {
				say(ERROR, "Could not find cpu with drc index "
				    "%x\n", my_drc_index);
				rc = -1;
				break;
			}

			rc = update_cpu_node(cpu, path, dr_info);
			if (rc)
				break;

			say(DEBUG, "Found cpu %s\n", cpu->name);
		}
	}

	closedir(d);

	if (rc)
		free_node(cpu_list);
	else
		dr_info->all_cpus = cpu_list;

	return rc;
}