xref: /openbmc/linux/drivers/acpi/acpica/utstate.c (revision e2f7a7772880458edff1b1cc5a988947229fac26)
195b482a8SLen Brown /*******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Module Name: utstate - state object support procedures
495b482a8SLen Brown  *
595b482a8SLen Brown  ******************************************************************************/
695b482a8SLen Brown 
795b482a8SLen Brown /*
895b482a8SLen Brown  * Copyright (C) 2000 - 2008, Intel Corp.
995b482a8SLen Brown  * All rights reserved.
1095b482a8SLen Brown  *
1195b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1295b482a8SLen Brown  * modification, are permitted provided that the following conditions
1395b482a8SLen Brown  * are met:
1495b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1595b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1695b482a8SLen Brown  *    without modification.
1795b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1895b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
1995b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2095b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2195b482a8SLen Brown  *    binary redistribution.
2295b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2395b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2495b482a8SLen Brown  *    from this software without specific prior written permission.
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2795b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2895b482a8SLen Brown  * Software Foundation.
2995b482a8SLen Brown  *
3095b482a8SLen Brown  * NO WARRANTY
3195b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3295b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3395b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3495b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3595b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3695b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3795b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3895b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3995b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4095b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4195b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4295b482a8SLen Brown  */
4395b482a8SLen Brown 
4495b482a8SLen Brown #include <acpi/acpi.h>
45*e2f7a777SLen Brown #include "accommon.h"
4695b482a8SLen Brown 
4795b482a8SLen Brown #define _COMPONENT          ACPI_UTILITIES
4895b482a8SLen Brown ACPI_MODULE_NAME("utstate")
4995b482a8SLen Brown 
5095b482a8SLen Brown /*******************************************************************************
5195b482a8SLen Brown  *
5295b482a8SLen Brown  * FUNCTION:    acpi_ut_create_pkg_state_and_push
5395b482a8SLen Brown  *
5495b482a8SLen Brown  * PARAMETERS:  Object          - Object to be added to the new state
5595b482a8SLen Brown  *              Action          - Increment/Decrement
5695b482a8SLen Brown  *              state_list      - List the state will be added to
5795b482a8SLen Brown  *
5895b482a8SLen Brown  * RETURN:      Status
5995b482a8SLen Brown  *
6095b482a8SLen Brown  * DESCRIPTION: Create a new state and push it
6195b482a8SLen Brown  *
6295b482a8SLen Brown  ******************************************************************************/
6395b482a8SLen Brown acpi_status
6495b482a8SLen Brown acpi_ut_create_pkg_state_and_push(void *internal_object,
6595b482a8SLen Brown 				  void *external_object,
6695b482a8SLen Brown 				  u16 index,
6795b482a8SLen Brown 				  union acpi_generic_state **state_list)
6895b482a8SLen Brown {
6995b482a8SLen Brown 	union acpi_generic_state *state;
7095b482a8SLen Brown 
7195b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
7295b482a8SLen Brown 
7395b482a8SLen Brown 	state =
7495b482a8SLen Brown 	    acpi_ut_create_pkg_state(internal_object, external_object, index);
7595b482a8SLen Brown 	if (!state) {
7695b482a8SLen Brown 		return (AE_NO_MEMORY);
7795b482a8SLen Brown 	}
7895b482a8SLen Brown 
7995b482a8SLen Brown 	acpi_ut_push_generic_state(state_list, state);
8095b482a8SLen Brown 	return (AE_OK);
8195b482a8SLen Brown }
8295b482a8SLen Brown 
8395b482a8SLen Brown /*******************************************************************************
8495b482a8SLen Brown  *
8595b482a8SLen Brown  * FUNCTION:    acpi_ut_push_generic_state
8695b482a8SLen Brown  *
8795b482a8SLen Brown  * PARAMETERS:  list_head           - Head of the state stack
8895b482a8SLen Brown  *              State               - State object to push
8995b482a8SLen Brown  *
9095b482a8SLen Brown  * RETURN:      None
9195b482a8SLen Brown  *
9295b482a8SLen Brown  * DESCRIPTION: Push a state object onto a state stack
9395b482a8SLen Brown  *
9495b482a8SLen Brown  ******************************************************************************/
9595b482a8SLen Brown 
9695b482a8SLen Brown void
9795b482a8SLen Brown acpi_ut_push_generic_state(union acpi_generic_state **list_head,
9895b482a8SLen Brown 			   union acpi_generic_state *state)
9995b482a8SLen Brown {
10095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_push_generic_state);
10195b482a8SLen Brown 
10295b482a8SLen Brown 	/* Push the state object onto the front of the list (stack) */
10395b482a8SLen Brown 
10495b482a8SLen Brown 	state->common.next = *list_head;
10595b482a8SLen Brown 	*list_head = state;
10695b482a8SLen Brown 
10795b482a8SLen Brown 	return_VOID;
10895b482a8SLen Brown }
10995b482a8SLen Brown 
11095b482a8SLen Brown /*******************************************************************************
11195b482a8SLen Brown  *
11295b482a8SLen Brown  * FUNCTION:    acpi_ut_pop_generic_state
11395b482a8SLen Brown  *
11495b482a8SLen Brown  * PARAMETERS:  list_head           - Head of the state stack
11595b482a8SLen Brown  *
11695b482a8SLen Brown  * RETURN:      The popped state object
11795b482a8SLen Brown  *
11895b482a8SLen Brown  * DESCRIPTION: Pop a state object from a state stack
11995b482a8SLen Brown  *
12095b482a8SLen Brown  ******************************************************************************/
12195b482a8SLen Brown 
12295b482a8SLen Brown union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
12395b482a8SLen Brown 						    **list_head)
12495b482a8SLen Brown {
12595b482a8SLen Brown 	union acpi_generic_state *state;
12695b482a8SLen Brown 
12795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_pop_generic_state);
12895b482a8SLen Brown 
12995b482a8SLen Brown 	/* Remove the state object at the head of the list (stack) */
13095b482a8SLen Brown 
13195b482a8SLen Brown 	state = *list_head;
13295b482a8SLen Brown 	if (state) {
13395b482a8SLen Brown 
13495b482a8SLen Brown 		/* Update the list head */
13595b482a8SLen Brown 
13695b482a8SLen Brown 		*list_head = state->common.next;
13795b482a8SLen Brown 	}
13895b482a8SLen Brown 
13995b482a8SLen Brown 	return_PTR(state);
14095b482a8SLen Brown }
14195b482a8SLen Brown 
14295b482a8SLen Brown /*******************************************************************************
14395b482a8SLen Brown  *
14495b482a8SLen Brown  * FUNCTION:    acpi_ut_create_generic_state
14595b482a8SLen Brown  *
14695b482a8SLen Brown  * PARAMETERS:  None
14795b482a8SLen Brown  *
14895b482a8SLen Brown  * RETURN:      The new state object. NULL on failure.
14995b482a8SLen Brown  *
15095b482a8SLen Brown  * DESCRIPTION: Create a generic state object.  Attempt to obtain one from
15195b482a8SLen Brown  *              the global state cache;  If none available, create a new one.
15295b482a8SLen Brown  *
15395b482a8SLen Brown  ******************************************************************************/
15495b482a8SLen Brown 
15595b482a8SLen Brown union acpi_generic_state *acpi_ut_create_generic_state(void)
15695b482a8SLen Brown {
15795b482a8SLen Brown 	union acpi_generic_state *state;
15895b482a8SLen Brown 
15995b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
16095b482a8SLen Brown 
16195b482a8SLen Brown 	state = acpi_os_acquire_object(acpi_gbl_state_cache);
16295b482a8SLen Brown 	if (state) {
16395b482a8SLen Brown 
16495b482a8SLen Brown 		/* Initialize */
16595b482a8SLen Brown 		memset(state, 0, sizeof(union acpi_generic_state));
16695b482a8SLen Brown 		state->common.descriptor_type = ACPI_DESC_TYPE_STATE;
16795b482a8SLen Brown 	}
16895b482a8SLen Brown 
16995b482a8SLen Brown 	return (state);
17095b482a8SLen Brown }
17195b482a8SLen Brown 
17295b482a8SLen Brown /*******************************************************************************
17395b482a8SLen Brown  *
17495b482a8SLen Brown  * FUNCTION:    acpi_ut_create_thread_state
17595b482a8SLen Brown  *
17695b482a8SLen Brown  * PARAMETERS:  None
17795b482a8SLen Brown  *
17895b482a8SLen Brown  * RETURN:      New Thread State. NULL on failure
17995b482a8SLen Brown  *
18095b482a8SLen Brown  * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
18195b482a8SLen Brown  *              to track per-thread info during method execution
18295b482a8SLen Brown  *
18395b482a8SLen Brown  ******************************************************************************/
18495b482a8SLen Brown 
18595b482a8SLen Brown struct acpi_thread_state *acpi_ut_create_thread_state(void)
18695b482a8SLen Brown {
18795b482a8SLen Brown 	union acpi_generic_state *state;
18895b482a8SLen Brown 
18995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_create_thread_state);
19095b482a8SLen Brown 
19195b482a8SLen Brown 	/* Create the generic state object */
19295b482a8SLen Brown 
19395b482a8SLen Brown 	state = acpi_ut_create_generic_state();
19495b482a8SLen Brown 	if (!state) {
19595b482a8SLen Brown 		return_PTR(NULL);
19695b482a8SLen Brown 	}
19795b482a8SLen Brown 
19895b482a8SLen Brown 	/* Init fields specific to the update struct */
19995b482a8SLen Brown 
20095b482a8SLen Brown 	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD;
20195b482a8SLen Brown 	state->thread.thread_id = acpi_os_get_thread_id();
20295b482a8SLen Brown 
20395b482a8SLen Brown 	/* Check for invalid thread ID - zero is very bad, it will break things */
20495b482a8SLen Brown 
20595b482a8SLen Brown 	if (!state->thread.thread_id) {
20695b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId"));
20795b482a8SLen Brown 		state->thread.thread_id = (acpi_thread_id) 1;
20895b482a8SLen Brown 	}
20995b482a8SLen Brown 
21095b482a8SLen Brown 	return_PTR((struct acpi_thread_state *)state);
21195b482a8SLen Brown }
21295b482a8SLen Brown 
21395b482a8SLen Brown /*******************************************************************************
21495b482a8SLen Brown  *
21595b482a8SLen Brown  * FUNCTION:    acpi_ut_create_update_state
21695b482a8SLen Brown  *
21795b482a8SLen Brown  * PARAMETERS:  Object          - Initial Object to be installed in the state
21895b482a8SLen Brown  *              Action          - Update action to be performed
21995b482a8SLen Brown  *
22095b482a8SLen Brown  * RETURN:      New state object, null on failure
22195b482a8SLen Brown  *
22295b482a8SLen Brown  * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
22395b482a8SLen Brown  *              to update reference counts and delete complex objects such
22495b482a8SLen Brown  *              as packages.
22595b482a8SLen Brown  *
22695b482a8SLen Brown  ******************************************************************************/
22795b482a8SLen Brown 
22895b482a8SLen Brown union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
22995b482a8SLen Brown 						      *object, u16 action)
23095b482a8SLen Brown {
23195b482a8SLen Brown 	union acpi_generic_state *state;
23295b482a8SLen Brown 
23395b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object);
23495b482a8SLen Brown 
23595b482a8SLen Brown 	/* Create the generic state object */
23695b482a8SLen Brown 
23795b482a8SLen Brown 	state = acpi_ut_create_generic_state();
23895b482a8SLen Brown 	if (!state) {
23995b482a8SLen Brown 		return_PTR(NULL);
24095b482a8SLen Brown 	}
24195b482a8SLen Brown 
24295b482a8SLen Brown 	/* Init fields specific to the update struct */
24395b482a8SLen Brown 
24495b482a8SLen Brown 	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE;
24595b482a8SLen Brown 	state->update.object = object;
24695b482a8SLen Brown 	state->update.value = action;
24795b482a8SLen Brown 
24895b482a8SLen Brown 	return_PTR(state);
24995b482a8SLen Brown }
25095b482a8SLen Brown 
25195b482a8SLen Brown /*******************************************************************************
25295b482a8SLen Brown  *
25395b482a8SLen Brown  * FUNCTION:    acpi_ut_create_pkg_state
25495b482a8SLen Brown  *
25595b482a8SLen Brown  * PARAMETERS:  Object          - Initial Object to be installed in the state
25695b482a8SLen Brown  *              Action          - Update action to be performed
25795b482a8SLen Brown  *
25895b482a8SLen Brown  * RETURN:      New state object, null on failure
25995b482a8SLen Brown  *
26095b482a8SLen Brown  * DESCRIPTION: Create a "Package State"
26195b482a8SLen Brown  *
26295b482a8SLen Brown  ******************************************************************************/
26395b482a8SLen Brown 
26495b482a8SLen Brown union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
26595b482a8SLen Brown 						   void *external_object,
26695b482a8SLen Brown 						   u16 index)
26795b482a8SLen Brown {
26895b482a8SLen Brown 	union acpi_generic_state *state;
26995b482a8SLen Brown 
27095b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object);
27195b482a8SLen Brown 
27295b482a8SLen Brown 	/* Create the generic state object */
27395b482a8SLen Brown 
27495b482a8SLen Brown 	state = acpi_ut_create_generic_state();
27595b482a8SLen Brown 	if (!state) {
27695b482a8SLen Brown 		return_PTR(NULL);
27795b482a8SLen Brown 	}
27895b482a8SLen Brown 
27995b482a8SLen Brown 	/* Init fields specific to the update struct */
28095b482a8SLen Brown 
28195b482a8SLen Brown 	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE;
28295b482a8SLen Brown 	state->pkg.source_object = (union acpi_operand_object *)internal_object;
28395b482a8SLen Brown 	state->pkg.dest_object = external_object;
28495b482a8SLen Brown 	state->pkg.index = index;
28595b482a8SLen Brown 	state->pkg.num_packages = 1;
28695b482a8SLen Brown 
28795b482a8SLen Brown 	return_PTR(state);
28895b482a8SLen Brown }
28995b482a8SLen Brown 
29095b482a8SLen Brown /*******************************************************************************
29195b482a8SLen Brown  *
29295b482a8SLen Brown  * FUNCTION:    acpi_ut_create_control_state
29395b482a8SLen Brown  *
29495b482a8SLen Brown  * PARAMETERS:  None
29595b482a8SLen Brown  *
29695b482a8SLen Brown  * RETURN:      New state object, null on failure
29795b482a8SLen Brown  *
29895b482a8SLen Brown  * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
29995b482a8SLen Brown  *              to support nested IF/WHILE constructs in the AML.
30095b482a8SLen Brown  *
30195b482a8SLen Brown  ******************************************************************************/
30295b482a8SLen Brown 
30395b482a8SLen Brown union acpi_generic_state *acpi_ut_create_control_state(void)
30495b482a8SLen Brown {
30595b482a8SLen Brown 	union acpi_generic_state *state;
30695b482a8SLen Brown 
30795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_create_control_state);
30895b482a8SLen Brown 
30995b482a8SLen Brown 	/* Create the generic state object */
31095b482a8SLen Brown 
31195b482a8SLen Brown 	state = acpi_ut_create_generic_state();
31295b482a8SLen Brown 	if (!state) {
31395b482a8SLen Brown 		return_PTR(NULL);
31495b482a8SLen Brown 	}
31595b482a8SLen Brown 
31695b482a8SLen Brown 	/* Init fields specific to the control struct */
31795b482a8SLen Brown 
31895b482a8SLen Brown 	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL;
31995b482a8SLen Brown 	state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
32095b482a8SLen Brown 
32195b482a8SLen Brown 	return_PTR(state);
32295b482a8SLen Brown }
32395b482a8SLen Brown 
32495b482a8SLen Brown /*******************************************************************************
32595b482a8SLen Brown  *
32695b482a8SLen Brown  * FUNCTION:    acpi_ut_delete_generic_state
32795b482a8SLen Brown  *
32895b482a8SLen Brown  * PARAMETERS:  State               - The state object to be deleted
32995b482a8SLen Brown  *
33095b482a8SLen Brown  * RETURN:      None
33195b482a8SLen Brown  *
33295b482a8SLen Brown  * DESCRIPTION: Release a state object to the state cache. NULL state objects
33395b482a8SLen Brown  *              are ignored.
33495b482a8SLen Brown  *
33595b482a8SLen Brown  ******************************************************************************/
33695b482a8SLen Brown 
33795b482a8SLen Brown void acpi_ut_delete_generic_state(union acpi_generic_state *state)
33895b482a8SLen Brown {
33995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_delete_generic_state);
34095b482a8SLen Brown 
34195b482a8SLen Brown 	/* Ignore null state */
34295b482a8SLen Brown 
34395b482a8SLen Brown 	if (state) {
34495b482a8SLen Brown 		(void)acpi_os_release_object(acpi_gbl_state_cache, state);
34595b482a8SLen Brown 	}
34695b482a8SLen Brown 	return_VOID;
34795b482a8SLen Brown }
348