示例#1
0
int
release_drc(int drc_index, uint32_t dev_type)
{
	int rc;

	say(DEBUG, "Releasing drc index 0x%x\n", drc_index);

	rc = dr_entity_sense(drc_index);
	if (rc != PRESENT)
		say(DEBUG, "drc_index %x sensor-state: %d\n%s\n", drc_index, rc,
		    entity_sense_error(rc));

	say(DEBUG, "Setting isolation state to 'isolate'\n");
	rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE);
	if (rc) {
		if (dev_type == PHB_DEV) {
			/* Workaround for CMVC 508114, where success returns
			 * too quickly
			 */
			int i = 0;
			while ((rc != 0) && (i < 20)) {
				rc = rtas_set_indicator(ISOLATION_STATE,
							drc_index,
							ISOLATE);
				sleep(1);
				i++;
			}
		}

		if (rc) {
			say(ERROR, "Isolation failed for %x with %d\n%s\n",
			    drc_index, rc, set_indicator_error(rc));
			return -1;
		}
	}

	say(DEBUG, "Setting allocation state to 'alloc unusable'\n");
	rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
	if (rc) {
		say(ERROR, "Unable to un-allocate drc %x from the partition "
		    "(%d)\n%s\n", drc_index, rc, set_indicator_error(rc));
		rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
		say(DEBUG, "UNISOLATE for drc %x, rc = %d\n", drc_index, rc);
		return -1;
	}

	rc = dr_entity_sense(drc_index);
	say(DEBUG, "drc_index %x sensor-state: %d\n%s\n", drc_index, rc,
	    entity_sense_error(rc));

	return 0;
}
示例#2
0
/**
 * release_hp_resource
 *
 * @param drc_index
 * @param power_domain
 * @returns 0 on success, !0 otherwise
 */
static int
release_hp_resource(struct dr_node *node)
{
	int rc;

	rc = remove_device_tree_nodes(node->ofdt_path);
	if (rc) {
		say(ERROR, "failed to remove kernel nodes for index 0x%x\n",
		    node->drc_index);
		return -EIO;
	}

	if (pci_hotplug_only)
		return 0;

	rc = rtas_set_indicator(DR_INDICATOR, node->drc_index, LED_OFF);
	if (rc) {
		say(ERROR, "failed to set led off for index 0x%x\n",
		    node->drc_index);
		return -EIO;
	}

	rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
	if (rc) {
		say(ERROR, "failed to isolate for index 0x%x\n",
		    node->drc_index);
		return -EIO;
	}

	rc = set_power(node->drc_power, POWER_OFF);
	if (rc) {
		struct stat sb;

		say(ERROR, "failed to power off for index 0x%x\n",
		    node->drc_index);

		if (!stat(IGNORE_HP_PO_PROP, &sb))
			say(ERROR, "Ignoring hot-plug power off failure.\n");
		else
			return -EIO;
	}

	return 0;
}
/**
 * acquire_hp_resource
 *
 * @param drc
 * @param of_path
 * @returns 0 on success, !0 otherwise
 */
static int
acquire_hp_resource(struct dr_connector *drc, char *of_path)
{
	struct of_node *new_nodes;
	int progress = ACQUIRE_HP_START;
	int state;
	int rc;

	state = dr_entity_sense(drc->index);
	if (state == PRESENT || state == NEED_POWER || state == PWR_ONLY) {
		rc = set_power(drc->powerdomain, POWER_ON);
		if (rc) {
			say(ERROR, "set power failed for 0x%x\n",
			    drc->powerdomain);
			return progress;
		}

		progress = ACQUIRE_HP_SPL;
		if (state == PWR_ONLY)
			state = dr_entity_sense(drc->index);
	}

	if (state == PRESENT || state == NEED_POWER) {
		rc = rtas_set_indicator(ISOLATION_STATE, drc->index,
				UNISOLATE);
		if (rc) {
			say(ERROR, "set ind failed for 0x%x\n", drc->index);
			return progress;
		}

		progress = ACQUIRE_HP_UNISO;
		if (state == NEED_POWER)
			state = dr_entity_sense(drc->index);
	}

	if (state < 0) {
		say(ERROR, "invalid state %d\n", state);
		return progress;
	}

	if (state == PRESENT) {
		new_nodes = configure_connector(drc->index);
		if (new_nodes == NULL)
			return progress;

		progress = ACQUIRE_HP_CFGCONN;

		rc = add_device_tree_nodes(of_path, new_nodes);
		if (rc) {
			say(ERROR, "add nodes failed for 0x%x\n", drc->index);
			return progress;
		}
	}

	return 0;
}
示例#4
0
/**
 * acquire_drc
 *
 */
int
acquire_drc(uint32_t drc_index)
{
	int rc;

	say(DEBUG, "Acquiring drc index 0x%x\n", drc_index);

	rc = dr_entity_sense(drc_index);
	if (rc != STATE_UNUSABLE) {
		say(ERROR, "Entity sense failed for drc %x with %d\n%s\n",
		    drc_index, rc, entity_sense_error(rc));
		return -1;
	}

	say(DEBUG, "Setting allocation state to 'alloc usable'\n");
	rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE);
	if (rc) {
		say(ERROR, "Allocation failed for drc %x with %d\n%s\n",
		    drc_index, rc, set_indicator_error(rc));
		return -1;
	}

	say(DEBUG, "Setting indicator state to 'unisolate'\n");
	rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
	if (rc) {
		int ret;
		rc = -1;

		say(ERROR, "Unisolate failed for drc %x with %d\n%s\n",
		    drc_index, rc, set_indicator_error(rc));
		ret = rtas_set_indicator(ALLOCATION_STATE, drc_index,
					 ALLOC_UNUSABLE);
		if (ret) {
			say(ERROR, "Failed recovery to unusable state after "
			    "unisolate failure for drc %x with %d\n%s\n",
			    drc_index, ret, set_indicator_error(ret));
		}
	}

	return rc;
}
示例#5
0
文件: dlpar.c 项目: 3null/linux
int dlpar_release_drc(u32 drc_index)
{
	int dr_status, rc;

	rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
		       DR_ENTITY_SENSE, drc_index);
	if (rc || dr_status != DR_ENTITY_PRESENT)
		return -1;

	rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE);
	if (rc)
		return rc;

	rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
	if (rc) {
		rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
		return rc;
	}

	return 0;
}
示例#6
0
文件: rtasd.c 项目: 0-T-0/ps4-linux
static int enable_surveillance(int timeout)
{
	int error;

	error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);

	if (error == 0)
		return 0;

	if (error == -EINVAL) {
		printk(KERN_DEBUG "rtasd: surveillance not supported\n");
		return 0;
	}

	printk(KERN_ERR "rtasd: could not update surveillance\n");
	return -1;
}
示例#7
0
static void __devinit pSeries_late_setup_cpu(int cpu)
{
	extern unsigned int default_distrib_server;

	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
		vpa_init(cpu); 
	}

#ifdef CONFIG_IRQ_ALL_CPUS
	/* Put the calling processor into the GIQ.  This is really only
	 * necessary from a secondary thread as the OF start-cpu interface
	 * performs this function for us on primary threads.
	 */
	/* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
	rtas_set_indicator(9005, default_distrib_server, 1);
#endif
}
示例#8
0
/**
 * process_led
 *
 * sets the given slot's led to the specified state. If the
 * return from set_led is bad, call the error_exit function to clean up
 * and exit the command.
 *
 * @param lslot pointer to slot we're setting
 * @param led setting for led
 */
static int
process_led(struct dr_node *node, int led)
{
	int rtas_rc;

	rtas_rc = rtas_set_indicator(DR_INDICATOR, node->drc_index, led);
	if (rtas_rc) {
		if (rtas_rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		return -1;
	}

	return 0;
}
示例#9
0
static int enable_surveillance(int timeout)
{
	int error;

	error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);

	if (error == 0)
		return 0;

	if (error == RTAS_NO_SUCH_INDICATOR) {
		printk(KERN_INFO "rtasd: surveillance not supported\n");
		return 0;
	}

	printk(KERN_ERR "rtasd: could not update surveillance\n");
	return -1;
}
/**
 * set_rtas_indicator - Set rtas indicator
 *
 * Call the rtas_set_indicator or rtas_set_dynamic_indicator librtas calls,
 * depending on whether the index indicates that the indicator is dynamic.
 *
 * @indicator	identification or attention indicator
 * @loc		location code of rtas indicator
 * @new_value	value to update indicator to
 *
 * Returns :
 *	rtas call return code
 */
static int
set_rtas_indicator(int indicator, struct loc_code *loc, int new_value)
{
	int	rc;
	int	rtas_token;
	char	err_buf[RTAS_ERROR_BUF_SIZE];

	rtas_token = get_rtas_token(indicator);
	if (rtas_token == -1)
		return -3; /* No such sensor implemented */

	if (loc->index == DYNAMIC_INDICATOR)
		rc = rtas_set_dynamic_indicator(rtas_token,
						new_value, (void *)loc);
	else
		rc = rtas_set_indicator(rtas_token, loc->index, new_value);

	switch (rc) {
	case 0:	/*success  */
		break;
	case -1:
		log_msg("Hardware error while setting the indicator at %s",
			loc->code);
		break;
	case -2:
		log_msg("Busy while setting the indicator at %s. "
			"Try again later", loc->code);
		break;
	case -3:
		log_msg("The indicator at %s is not implemented", loc->code);
		break;
	default:
		librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE);

		log_msg("Could not set %ssensor %s indicators,\n%s",
			(loc->index == DYNAMIC_INDICATOR) ? "dynamic " : "",
			get_indicator_desc(indicator), err_buf);
		break;
	}

	return rc;
}
示例#11
0
/**
 * remove_work
 *
 * Removes nodes associated a PCI slot from the
 * Open Firmware device tree and isolates and powers off the PCI slot.
 *
 * A remove may be specified by the location code of the  PCI slot.
 * Unless the user specifies the -I flag, the slot is identified to
 * the user.
 * Nodes representing the device(s) are removed from the
 * Open Firmware device tree. The slot is isolated and powered off,
 * and the LED is turned off.
 *
 * @returns pointer slot on success, NULL on failure
 */
static struct dr_node *
remove_work(struct options *opts, struct dr_node *all_nodes)
{
	struct dr_node *node;
	struct dr_node *child;
	int rc;
	int usr_key = USER_CONT;

	node = find_slot(opts->usr_drc_name, all_nodes);
	if (node == NULL)
		return NULL;

	say(DEBUG, "found node: drc name=%s, index=0x%x, path=%s\n",
	     node->drc_name, node->drc_index, node->ofdt_path);

	/* Prompt user only if not in noprompt mode */
	if (0 == opts->noprompt) {
		if (!opts->no_ident)
			usr_key = identify_slot(node);

		if (usr_key == USER_QUIT) {
			if (node->children == NULL)
				process_led(node, LED_OFF);
			else
				process_led(node, LED_ON);
			return NULL;
		}
	}

	/* Turn on the LED while we go do some work. */
	if (process_led(node, LED_ON))
		return NULL;

	/* Make sure there's something there to remove. */
	if (node->children == NULL) {
		process_led(node, LED_OFF);
		say(ERROR, "There is no configured card to remove from the "
		    "specified PCI slot.\n");
		return NULL;
	}

	/* Make sure all the devices are
	 * not configured before proceeding
	 */
	if (get_hp_adapter_status(node->drc_name) == CONFIG) {
		say(DEBUG, "unconfiguring adapter in slot[%s]\n",
		    node->drc_name);
		set_hp_adapter_status(PHP_UNCONFIG_ADAPTER, node->drc_name);

		int rc = get_hp_adapter_status(node->drc_name);
		if (rc != NOT_CONFIG) {
			say(ERROR, "Unconfig adapter failed.\n");
			return NULL;
		}
	} else {
		/* In certain cases such as a complete failure of the
		 * adapter there may not have been the possibility to clean
		 * up everything. Mark these adapaters for additional
		 * processing later.
		 */
		node->post_replace_processing = 1;
	}

	/* Call subroutine to remove node(s) from
	 * the device tree.
	 */
	for (child = node->children; child; child = child->next) {
		rc = remove_device_tree_nodes(child->ofdt_path);
		if (rc) {
			say(ERROR, "%s", sw_error);
			rtas_set_indicator(ISOLATION_STATE, node->drc_index,
					   ISOLATE);
			set_power(node->drc_power, POWER_OFF);
			return NULL;
		}
	}

	/* We have to isolate and power off before
	 * allowing the user to physically remove
	 * the card.
	 */
	say(DEBUG, "is calling rtas_set_indicator(ISOLATE index 0x%x)\n",
	    node->drc_index);

	rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		set_power(node->drc_power, POWER_OFF);
		return NULL;
	}

	say(DEBUG, "is calling set_power(POWER_OFF index 0x%x, power_domain "
	    "0x%x)\n", node->drc_index, node->drc_power);

	rc = set_power(node->drc_power, POWER_OFF);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		set_power(node->drc_power, POWER_OFF);
		return NULL;
	}

	return node;
}
示例#12
0
/**
 * do_add
 *
 * Prepares a PCI hot plug slot for adding an adapter, then
 * configures the adapter and any PCI adapters below into
 * the Open Firmware device tree.
 *
 * Verifies that a given hot plug PCI slot does not have an adapter
 * already connected, identifies the slot to the user unless requested not
 * to with the -i flag, prompts the user to connect the adapter, powers
 * the slot on, and calls configure connector. When configure connector
 * completes and returns the new node(s) for the new PCI adapter and any
 * attached devices then the Open Firmware device tree is
 * updated to reflect the new devices.
 */
static int
do_add(struct options *opts, struct dr_node *all_nodes)
{
	struct dr_node *node;
	int usr_key = USER_CONT;
	int rc;

	node = find_slot(opts->usr_drc_name, all_nodes);
	if (node == NULL)
		return -1;

	/* Prompt user only if in interactive mode. */
	if (0 == opts->noprompt) {
		if (!opts->no_ident)
			usr_key = identify_slot(node);

		if (usr_key == USER_QUIT) {
			if (node->children == NULL)
				process_led(node, LED_OFF);
			else
				process_led(node, LED_ON);
			return 0;
		}
	}

	if (node->children != NULL) {
		/* If there's already something here, turn the
		 * LED on and exit with user error.
		 */
		process_led(node, LED_ON);
		say(ERROR, "The specified PCI slot is already occupied.\n");
		return -1;
	}


	/* Now it's time to isolate, power off, set the
	 * action LED, and prompt the user to put the
	 * card in.
	 */

	say(DEBUG, "is calling rtas_set_indicator(ISOLATE index 0x%x)\n",
	    node->drc_index);

	rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		set_power(node->drc_power, POWER_OFF);
		return -1;
	}

	say(DEBUG, "is calling set_power(POWER_OFF index 0x%x, "
	    "power_domain 0x%x) \n", node->drc_index, node->drc_power);

	rc = set_power(node->drc_power, POWER_OFF);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		return -1;
	}

	if (0 == opts->noprompt) {
		/* Prompt user to put in card and to press
		 * Enter to continue or other key to exit.
		 */
		if (process_led(node, LED_ACTION))
			return -1;

		printf("The visual indicator for the specified PCI slot has\n"
			"been set to the action state. Insert the PCI card\n"
			"into the identified slot, connect any devices to be\n"
			"configured and press Enter to continue. Enter x to "
			"exit.\n");

		if (!(getchar() == '\n')) {
			process_led(node, LED_OFF);
			return 0;
		}
	}

	/* Call the routine which determines
	 * what the user wants and does it.
	 */
	rc = add_work(opts, node);
	if (rc)
		return rc;

	say(DEBUG, "is calling enable_slot to config adapter\n");

	/* Try to config the adapter */
	set_hp_adapter_status(PHP_CONFIG_ADAPTER, node->drc_name);

	return 0;
}
示例#13
0
/**
 * add_work
 *
 * Prepares a PCI hot plug slot for adding an adapter, then
 * configures the adapter and any PCI adapters below into the
 * kernel's and /proc's Open Firmware device tree.
 *
 * If there are any errors from the RTAS routines,
 * the slot is powered off, isolated, and the LED is turned off. No
 * configuration is completed.
 * If the OF tree cannot be updated, the slot is powered
 * off, isolated, and the LED is turned off.
 *
 * @param opts
 * @param slot
 * @returns 0 on success, !0 on failure
 */
static int
add_work(struct options *opts, struct dr_node *node)
{
	int pow_state;	/* Tells us if power was turned on when	 */
	int iso_state;	/* Tells us isolation state after 	 */
	int rc;
	struct of_node *new_nodes;/* nodes returned from configure_connector */

	/* if we're continuing, set LED_ON and see if a card is really there. */
	if (process_led(node, LED_ON))
		return -1;

	say(DEBUG, "is calling card_present\n");
	rc = card_present(opts, node, &pow_state, &iso_state);
	if (!rc) {
		say(ERROR, "No PCI card was detected in the specified "
		    "PCI slot.\n");
		rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
		set_power(node->drc_power, POWER_OFF);
		return -1;
	}

	if (!pow_state) {
		say(DEBUG, "is calling set_power(POWER_ON index 0x%x, "
		    "power_domain 0x%x\n", node->drc_index, node->drc_power);

		rc = set_power(node->drc_power, POWER_ON);
		if (rc) {
			if (rc == HW_ERROR)
				say(ERROR, "%s", hw_error);
			else if (rc == SPEED_ERROR)
				say(ERROR, "%s", speed_error);
			else
				say(ERROR, "%s", sw_error);

			rtas_set_indicator(ISOLATION_STATE, node->drc_index,
					   ISOLATE);
			set_power(node->drc_power, POWER_OFF);
			return -1;
		}
	}

	if (!iso_state) {
		say(DEBUG, "calling rtas_set_indicator(UNISOLATE index 0x%x)\n",
		    node->drc_index);

		rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index,
					UNISOLATE);
		if (rc) {
			if (rc == HW_ERROR)
				say(ERROR, "%s", hw_error);
			else
				say(ERROR, "%s", sw_error);

			rtas_set_indicator(ISOLATION_STATE, node->drc_index,
					   ISOLATE);
			set_power(node->drc_power, POWER_OFF);
			return -1;
		}
	}

	/* Now go get all the new nodes for this adapter. If
	 * the return status requires a message, print it out
	 * and exit, otherwise, add the nodes to the OF tree.
	 */
	new_nodes = configure_connector(node->drc_index);
	if (new_nodes == NULL) {
		rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
		set_power(node->drc_power, POWER_OFF);
		return -1;
	}

	say(DEBUG, "Adding %s to %s\n", new_nodes->name, node->ofdt_path);
	rc = add_device_tree_nodes(node->ofdt_path, new_nodes);
	if (rc) {
		say(DEBUG, "add_device_tree_nodes failed at %s\n",
		    node->ofdt_path);
		say(ERROR, "%s", sw_error);
		rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
		set_power(node->drc_power, POWER_OFF);
		return -1;
	}

	return 0;
}
示例#14
0
/**
 * card_present
 * @brief Determines if there is a card present in the specified slot
 *
 * Attempt to check if a card is present. If we get a definite answer,
 * return that and indicate that we did not turn the power on. Depending
 * on the adapter, we may have to power on and we may have to unisolate
 * to determine if a card is present. If that's the case, power on
 * maybe isolate and try sensing again. If we hit fatal errors, call
 * error_exit to clean up and exit the command.
 *
 * @param opts
 * @param slot pointer to slot we're checking
 * @param power_state state of power when we leave this routine
 * @param isolate_state state of isolation when we leave this routine
 * @returns EMPTY or PRESENT
 */
static int
card_present(struct options *opts, struct dr_node *node, int *power_state,
	     int *isolate_state)
{
	int state, rc;

	*power_state = POWER_OFF;	/* initialize */
	*isolate_state = ISOLATE;

	state = check_card_presence(opts, node);
	if ((state == EMPTY) || (state == PRESENT))
		return state;

	else if (state == HW_ERROR) {
		say(ERROR, "%s", hw_error);
		return -1;
	}
	else if ((state == NEED_POWER) || (state == PWR_ONLY)) {
		/* set power on, and if needed, unisolate too */
		rc = set_power(node->drc_power, POWER_ON);
		if (rc) {
			if (rc == HW_ERROR) {
				say(ERROR, "%s", hw_error);
				return -1;
			}
			else if (rc == SPEED_ERROR) {
				say(ERROR, "%s", speed_error);
				set_power(node->drc_power, POWER_OFF);
				return -1;
			}
			/* Catch any other errors.  */
			else {
				say(ERROR, "%s", sw_error);
				set_power(node->drc_power, POWER_OFF);
				return -1;
			}
		}

		*power_state = POWER_ON;
		if (state == NEED_POWER) {
			/* If we get here, we have power on now
			 * but we still need to unisolate
			 */
			rc = rtas_set_indicator(ISOLATION_STATE,
						node->drc_index, UNISOLATE);
			if (rc) {
				if (rc == HW_ERROR)
					say(ERROR, "%s", hw_error);
				else
					say(ERROR, "%s", sw_error);

				rtas_set_indicator(ISOLATION_STATE,
						   node->drc_index, ISOLATE);
				set_power(node->drc_power, POWER_OFF);
				return -1;
			}
			*isolate_state = UNISOLATE;
		}

		/* Now we have power on, and the unisolate is done
		 * if it was needed. check for card again.
		 */
		state = check_card_presence(opts, node);
		if ((state == EMPTY) || (state == PRESENT))
			return state;

		if (state) {
			if (rc == HW_ERROR)
				say(ERROR, "%s", hw_error);
			else
				say(ERROR, "%s", sw_error);

			rtas_set_indicator(ISOLATION_STATE, node->drc_index,
					   ISOLATE);
			set_power(node->drc_power, POWER_OFF);
			return -1;
		}
	}
	else {
  		/* catch any other errors from first dr_entity_sense */
		say(ERROR, "%s", sw_error);
	}

	return state;
}