Пример #1
0
acpi_status
bm_get_status (
	BM_DEVICE		*device)
{
	acpi_status           status = AE_OK;

	if (!device) {
		return AE_BAD_PARAMETER;
	}

	device->status = BM_STATUS_UNKNOWN;

	/*
	 * Dynamic Status?
	 * ---------------
	 * If _STA isn't present we just return the default status.
	 */
	if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) {
		device->status = BM_STATUS_DEFAULT;
		return AE_OK;
	}

	/*
	 * Evaluate _STA:
	 * --------------
	 */
	status = bm_evaluate_simple_integer(device->acpi_handle, "_STA",
		&(device->status));

	return status;
}
Пример #2
0
acpi_status
bm_get_power_state (
	BM_NODE			*node)
{
	acpi_status             status = AE_OK;
	BM_DEVICE               *device = NULL;

	FUNCTION_TRACE("bm_get_power_state");

	if (!node || !node->parent) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	device = &(node->device);

	device->power.state = ACPI_STATE_UNKNOWN;

	/*
	 * Power Control?
	 * --------------
	 * If this device isn't directly power manageable (e.g. doesn't
	 * include _PR0/_PS0) then there's nothing to do (state is static).
	 */
	if (!BM_IS_POWER_CONTROL(device)) {
		return_ACPI_STATUS(AE_OK);
	}

	/*
	 * Parent Present?
	 * ---------------
	 * Make sure the parent is present before mucking with the child.
	 */
	if (!BM_NODE_PRESENT(node->parent)) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}
	
	/*
	 * Get Power State:
	 * ----------------
	 * Either directly (via _PSC) or inferred (via power resource
	 * dependencies).
	 */
	if (BM_IS_POWER_STATE(device)) {
		status = bm_evaluate_simple_integer(device->acpi_handle,
			"_PSC", &(device->power.state));
	}
	else {
		status = bm_get_inferred_power_state(device);
	}

	if (ACPI_SUCCESS(status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Device [%02x] is at power state [D%d].\n", device->handle, device->power.state));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Error getting power state for device [%02x]\n", device->handle));
	}

	return_ACPI_STATUS(status);
}
Пример #3
0
static int
ac_osl_proc_read_status (
	char			*page,
	char			**start,
	off_t			off,
	int 			count,
	int 			*eof,
	void			*context)
{
	acpi_status 		status = AE_OK;
	AC_CONTEXT		*ac_adapter = NULL;
	char			*p = page;
	int			len;

	if (!context) {
		goto end;
	}

	ac_adapter = (AC_CONTEXT*)context;

	/* don't get status more than once for a single proc read */
	if (off != 0) {
		goto end;
	}

	status = bm_evaluate_simple_integer(ac_adapter->acpi_handle,
		"_PSR", &(ac_adapter->is_online));
	if (ACPI_FAILURE(status)) {
		p += sprintf(p, "Error reading AC Adapter status\n");
		goto end;
	}

	if (ac_adapter->is_online) {
		p += sprintf(p, "Status:                  %s\n",
			AC_ON_LINE);
	}
	else {
		p += sprintf(p, "Status:                  %s\n",
			AC_OFF_LINE);
	}

end:
	len = (p - page);
	if (len <= off+count) *eof = 1;
	*start = page + off;
	len -= off;
	if (len>count) len = count;
	if (len<0) len = 0;

	return(len);
}
Пример #4
0
acpi_status
ec_install_gpe_handler (
	EC_CONTEXT              *ec)
{
	acpi_status             status = AE_OK;

	FUNCTION_TRACE("ec_install_gpe_handler");

	if (!ec) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/*
	 * Evaluate _GPE:
	 * --------------
	 * Evaluate the "_GPE" object (required) to find out which GPE bit
	 * is used by this EC to signal events (SCIs).
	 */
	status = bm_evaluate_simple_integer(ec->acpi_handle,
		"_GPE", &(ec->gpe_bit));
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Install GPE Handler:
	 * --------------------
	 * Install a handler for this EC's GPE bit.
	 */
	status = acpi_install_gpe_handler(ec->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED,
		&ec_gpe_handler, ec);
	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "acpi_install_gpe_handler() failed for GPE bit [%02x] with status [%08x].\n", ec->gpe_bit, status));
		ec->gpe_bit = EC_GPE_UNKNOWN;
		return_ACPI_STATUS(status);
	}

	return_ACPI_STATUS(status);
}
Пример #5
0
acpi_status
tz_get_temperature (
	TZ_CONTEXT		*tz)
{
	acpi_status             status = AE_OK;

	FUNCTION_TRACE("tz_get_temperature");

	if (!tz) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/*
	 * Evaluate the _TMP method to get the current temperature.
	 */
	status = bm_evaluate_simple_integer(tz->acpi_handle, "_TMP", &(tz->policy.temperature));
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %d d_k\n", tz->policy.temperature));

	return_ACPI_STATUS(status);
}
Пример #6
0
acpi_status
ec_add_device(
	BM_HANDLE               device_handle,
	void                    **context)
{
	acpi_status             status = AE_OK;
	BM_DEVICE		*device = NULL;
	EC_CONTEXT              *ec = NULL;
	u8                      gpe_handler = FALSE;
	u8                      space_handler = FALSE;

	FUNCTION_TRACE("ec_add_device");

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding EC device [%02x].\n", device_handle));

	if (!context || *context) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/*
	 * Get information on this device.
	 */
	status = bm_get_device_info(device_handle, &device);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Allocate a new EC_CONTEXT structure.
	 */
	ec = acpi_os_callocate(sizeof(EC_CONTEXT));
	if (!ec) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	ec->device_handle = device->handle;
	ec->acpi_handle = device->acpi_handle;

	/*
	 * Get the I/O port addresses for the command/status and data ports.
	 */
	status = ec_get_port_values(ec);
	if (ACPI_FAILURE(status)) {
		goto end;
	}

	/*
	 * See if we need to obtain the global lock for EC transactions.
	 */
	status = bm_evaluate_simple_integer(ec->acpi_handle, "_GLK",
		&ec->use_global_lock);
	if (status == AE_NOT_FOUND) {
		ec->use_global_lock = 0;
	}
	else if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "EC _GLK failed\n"));
		goto end;
	}

	/*
	 * Install a handler for servicing this EC's GPE.
	 */
	status = ec_install_gpe_handler(ec);
	if (ACPI_FAILURE(status)) {
		goto end;
	}
	else {
		gpe_handler = TRUE;
	}

	/*
	 * Install a handler for servicing this EC's address space.
	 */
	status = ec_install_space_handler(ec);
	if (ACPI_FAILURE(status)) {
		goto end;
	}
	else {
		space_handler = TRUE;
	}

	/*
	 * Create a semaphore to serialize EC transactions.
	 */
	status = acpi_os_create_semaphore(1,1, &(ec->mutex));
	if (ACPI_FAILURE(status)) {
		goto end;
	}

	/*
	 * Context now contains information specific to this EC.  Note
	 * that we'll get this pointer back on every ec_request() and
	 * ec_notify().
	 */
	*context = ec;

	ec_print(ec);

end:
	if (ACPI_FAILURE(status)) {

		if (gpe_handler) {
			ec_remove_gpe_handler(ec);
		}

		if (space_handler) {
			ec_remove_space_handler(ec);
		}

		if (ec->mutex) {
			acpi_os_delete_semaphore(ec->mutex);
		}

		acpi_os_free(ec);
	}

	return_ACPI_STATUS(status);
}
Пример #7
0
acpi_status
tz_add_device (
	BM_HANDLE               device_handle,
	void                    **context)
{
	acpi_status             status = AE_OK;
	TZ_CONTEXT              *tz = NULL;
	BM_DEVICE		*device = NULL;
	acpi_handle             tmp_handle = NULL;
	static u32		zone_count = 0;

	FUNCTION_TRACE("tz_add_device");

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding thermal zone [%02x].\n", device_handle));

	if (!context || *context) {
		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid context for device [%02x].\n", device_handle));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/*
	 * Get information on this device.
	 */
	status = bm_get_device_info(device_handle, &device);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Allocate a new Thermal Zone device.
	 */
	tz = acpi_os_callocate(sizeof(TZ_CONTEXT));
	if (!tz) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	tz->device_handle = device->handle;
	tz->acpi_handle = device->acpi_handle;

	/* TBD: How to manage 'uid' when zones are Pn_p? */
	sprintf(tz->uid, "%d", zone_count++);

	/*
	 * Temperature:
	 * ------------
	 * Make sure we can read the zone's current temperature (_TMP).
	 * If we can't, there's no use in doing any policy (abort).
	 */
	status = tz_get_temperature(tz);
	if (ACPI_FAILURE(status))
		goto end;

	/*
	 * Polling Frequency:
	 * ------------------
	 * If _TZP doesn't exist use the OS default polling frequency.
	 */
	status = bm_evaluate_simple_integer(tz->acpi_handle, "_TZP", &(tz->policy.polling_freq));
	if (ACPI_FAILURE(status)) {
		tz->policy.polling_freq = TZP;
	}
	status = AE_OK;

	/*
	 * Cooling Preference:
	 * -------------------
	 * Default to ACTIVE (noisy) cooling until policy decides otherwise.
	 * Note that _SCP is optional.
	 */
	tz_set_cooling_preference(tz, TZ_COOLING_MODE_ACTIVE);

	/*
	 * Start Policy:
	 * -------------
	 * Thermal policy is included in the kernel (this driver) because
	 * of the critical role it plays in avoiding nuclear meltdown. =O
	 */
	status = tz_policy_add_device(tz);
	if (ACPI_FAILURE(status))
		goto end;

	status = tz_osl_add_device(tz);
	if (ACPI_FAILURE(status))
		goto end;

	*context = tz;

	tz_print(tz);

end:
	if (ACPI_FAILURE(status))
		acpi_os_free(tz);

	return_ACPI_STATUS(status);
}
Пример #8
0
acpi_status
tz_get_thresholds (
	TZ_CONTEXT		*tz)
{
	acpi_status		status = AE_OK;
	TZ_THRESHOLDS		*thresholds = NULL;
	u32			value = 0;
	u32                     i = 0;

	FUNCTION_TRACE("acpi_tz_get_thresholds");

	if (!tz) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	thresholds = &(tz->policy.thresholds);

	/* Critical Shutdown (required) */

	status = bm_evaluate_simple_integer(tz->acpi_handle, "_CRT", &value);
	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
		return_ACPI_STATUS(status);
	}
	else {
		thresholds->critical.temperature = value;
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%d]\n", thresholds->critical.temperature));

	}

	/* Critical Sleep (optional) */

	status = bm_evaluate_simple_integer(tz->acpi_handle, "_HOT", &value);
	if (ACPI_FAILURE(status)) {
		thresholds->hot.is_valid = 0;
		thresholds->hot.temperature = 0;
	}
	else {
		thresholds->hot.is_valid = 1;
		thresholds->hot.temperature = value;
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%d]\n", thresholds->hot.temperature));
	}

	/* Passive: Processors (optional) */

	status = bm_evaluate_simple_integer(tz->acpi_handle, "_PSV", &value);
	if (ACPI_FAILURE(status)) {
		thresholds->passive.is_valid = 0;
		thresholds->passive.temperature = 0;
	}
	else {
		thresholds->passive.is_valid = 1;
		thresholds->passive.temperature = value;

		status = bm_evaluate_simple_integer(tz->acpi_handle, "_TC1", &value);
		if (ACPI_FAILURE(status)) {
			thresholds->passive.is_valid = 0;
		}
		thresholds->passive.tc1 = value;

		status = bm_evaluate_simple_integer(tz->acpi_handle, "_TC2", &value);
		if (ACPI_FAILURE(status)) {
			thresholds->passive.is_valid = 0;
		}
		thresholds->passive.tc2 = value;

		status = bm_evaluate_simple_integer(tz->acpi_handle, "_TSP", &value);
		if (ACPI_FAILURE(status)) {
			thresholds->passive.is_valid = 0;
		}
		thresholds->passive.tsp = value;

		status = bm_evaluate_reference_list(tz->acpi_handle, "_PSL", &(thresholds->passive.devices));
		if (ACPI_FAILURE(status)) {
			thresholds->passive.is_valid = 0;
		}

		if (thresholds->passive.is_valid) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%d]\n", thresholds->passive.temperature));
		}
		else {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid passive threshold\n"));
		}
	}

	/* Active: Fans, etc. (optional) */

	for (i=0; i<TZ_MAX_ACTIVE_THRESHOLDS; i++) {

		char name[5] = {'_','A','C',('0'+i),'\0'};

		status = bm_evaluate_simple_integer(tz->acpi_handle, name, &value);
		if (ACPI_FAILURE(status)) {
			thresholds->active[i].is_valid = 0;
			thresholds->active[i].temperature = 0;
			break;
		}

		thresholds->active[i].temperature = value;
		name[2] = 'L';

		status = bm_evaluate_reference_list(tz->acpi_handle, name, &(thresholds->active[i].devices));
		if (ACPI_SUCCESS(status)) {
			thresholds->active[i].is_valid = 1;
			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%d]\n", i, thresholds->active[i].temperature));
		}
		else {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
		}
	}

	return_ACPI_STATUS(AE_OK);
}
Пример #9
0
acpi_status
bm_get_pm_capabilities (
	BM_NODE			*node)
{
	acpi_status             status = AE_OK;
	BM_DEVICE		*device = NULL;
	BM_DEVICE		*parent_device = NULL;
	acpi_handle             acpi_handle = NULL;
	BM_POWER_STATE          dx_supported = ACPI_STATE_UNKNOWN;
	char                    object_name[5] = {'_','S','0','D','\0'};
	u32                     i = 0;

	FUNCTION_TRACE("bm_get_pm_capabilities");

	if (!node || !node->parent) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	device = &(node->device);
	parent_device = &(node->parent->device);

	/*
	 * Power Management Flags:
	 * -----------------------
	 */
	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_POWER_STATE;
	}

	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_INRUSH_CURRENT;
	}

	if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW",
		&acpi_handle))) {
		device->power.flags |= BM_FLAGS_WAKE_CAPABLE;
	}

	/*
	 * Device Power State:
	 * -------------------
	 * Note that we can't get the device's power state until we've
	 * initialized all power resources, so for now we just set to
	 * unknown.
	 */
	device->power.state = ACPI_STATE_UNKNOWN;

	/*
	 * Dx Supported in S0:
	 * -------------------
	 * Figure out which Dx states are supported by this device for the
	 * S0 (working) state.  Note that D0 and D3 are required (assumed).
	 */
	device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT |
		BM_FLAGS_D3_SUPPORT;

	if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1",
		&acpi_handle))) ||
		(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1",
		&acpi_handle)))) {
		device->power.dx_supported[ACPI_STATE_S0] |=
			BM_FLAGS_D1_SUPPORT;
	}

	if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2",
		&acpi_handle))) ||
		(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2",
		&acpi_handle)))) {
		device->power.dx_supported[ACPI_STATE_S0] |=
			BM_FLAGS_D2_SUPPORT;
	}

	/*
	 * Dx Supported in S1-S5:
	 * ----------------------
	 * Figure out which Dx states are supported by this device for
	 * all other Sx states.
	 */
	for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) {

		/*
		 * D3 support is assumed (off is always possible!).
		 */
		device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT;

		/*
		 * Evalute _Sx_d:
		 * -------------
		 * Which returns the highest (power) Dx state supported in
		 * this system (Sx) state.  We convert this value to a bit
		 * mask of supported states (conceptually simpler).
		 */
		status = bm_evaluate_simple_integer(device->acpi_handle,
			object_name, &dx_supported);
		if (ACPI_SUCCESS(status)) {
			switch (dx_supported) {
			case 0:
				device->power.dx_supported[i] |=
					BM_FLAGS_D0_SUPPORT;
				/* fall through */
			case 1:
				device->power.dx_supported[i] |=
					BM_FLAGS_D1_SUPPORT;
				/* fall through */
			case 2:
				device->power.dx_supported[i] |=
					BM_FLAGS_D2_SUPPORT;
				/* fall through */
			case 3:
				device->power.dx_supported[i] |=
					BM_FLAGS_D3_SUPPORT;
				break;
			}

			/*
			 * Validate:
			 * ---------
			 * Mask of any states that _Sx_d falsely advertises
			 * (e.g.claims D1 support but neither _PR2 or _PS2
			 * exist).  In other words, S1-S5 can't offer a Dx
			 * state that isn't supported by S0.
			 */
			device->power.dx_supported[i] &=
				device->power.dx_supported[ACPI_STATE_S0];
		}

		object_name[2]++;
	}

	return_ACPI_STATUS(AE_OK);
}