1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /******************************************************************************* 3 * 4 * Module Name: utstate - state object support procedures 5 * 6 ******************************************************************************/ 7 8 #include <acpi/acpi.h> 9 #include "accommon.h" 10 11 #define _COMPONENT ACPI_UTILITIES 12 ACPI_MODULE_NAME("utstate") 13 14 /******************************************************************************* 15 * 16 * FUNCTION: acpi_ut_push_generic_state 17 * 18 * PARAMETERS: list_head - Head of the state stack 19 * state - State object to push 20 * 21 * RETURN: None 22 * 23 * DESCRIPTION: Push a state object onto a state stack 24 * 25 ******************************************************************************/ 26 void 27 acpi_ut_push_generic_state(union acpi_generic_state **list_head, 28 union acpi_generic_state *state) 29 { 30 ACPI_FUNCTION_ENTRY(); 31 32 /* Push the state object onto the front of the list (stack) */ 33 34 state->common.next = *list_head; 35 *list_head = state; 36 return; 37 } 38 39 /******************************************************************************* 40 * 41 * FUNCTION: acpi_ut_pop_generic_state 42 * 43 * PARAMETERS: list_head - Head of the state stack 44 * 45 * RETURN: The popped state object 46 * 47 * DESCRIPTION: Pop a state object from a state stack 48 * 49 ******************************************************************************/ 50 51 union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state 52 **list_head) 53 { 54 union acpi_generic_state *state; 55 56 ACPI_FUNCTION_ENTRY(); 57 58 /* Remove the state object at the head of the list (stack) */ 59 60 state = *list_head; 61 if (state) { 62 63 /* Update the list head */ 64 65 *list_head = state->common.next; 66 } 67 68 return (state); 69 } 70 71 /******************************************************************************* 72 * 73 * FUNCTION: acpi_ut_create_generic_state 74 * 75 * PARAMETERS: None 76 * 77 * RETURN: The new state object. NULL on failure. 78 * 79 * DESCRIPTION: Create a generic state object. Attempt to obtain one from 80 * the global state cache; If none available, create a new one. 81 * 82 ******************************************************************************/ 83 84 union acpi_generic_state *acpi_ut_create_generic_state(void) 85 { 86 union acpi_generic_state *state; 87 88 ACPI_FUNCTION_ENTRY(); 89 90 state = acpi_os_acquire_object(acpi_gbl_state_cache); 91 if (state) { 92 93 /* Initialize */ 94 state->common.descriptor_type = ACPI_DESC_TYPE_STATE; 95 } 96 97 return (state); 98 } 99 100 /******************************************************************************* 101 * 102 * FUNCTION: acpi_ut_create_thread_state 103 * 104 * PARAMETERS: None 105 * 106 * RETURN: New Thread State. NULL on failure 107 * 108 * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used 109 * to track per-thread info during method execution 110 * 111 ******************************************************************************/ 112 113 struct acpi_thread_state *acpi_ut_create_thread_state(void) 114 { 115 union acpi_generic_state *state; 116 117 ACPI_FUNCTION_ENTRY(); 118 119 /* Create the generic state object */ 120 121 state = acpi_ut_create_generic_state(); 122 if (!state) { 123 return (NULL); 124 } 125 126 /* Init fields specific to the update struct */ 127 128 state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD; 129 state->thread.thread_id = acpi_os_get_thread_id(); 130 131 /* Check for invalid thread ID - zero is very bad, it will break things */ 132 133 if (!state->thread.thread_id) { 134 ACPI_ERROR((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId")); 135 state->thread.thread_id = (acpi_thread_id) 1; 136 } 137 138 return ((struct acpi_thread_state *)state); 139 } 140 141 /******************************************************************************* 142 * 143 * FUNCTION: acpi_ut_create_update_state 144 * 145 * PARAMETERS: object - Initial Object to be installed in the state 146 * action - Update action to be performed 147 * 148 * RETURN: New state object, null on failure 149 * 150 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used 151 * to update reference counts and delete complex objects such 152 * as packages. 153 * 154 ******************************************************************************/ 155 156 union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object 157 *object, u16 action) 158 { 159 union acpi_generic_state *state; 160 161 ACPI_FUNCTION_ENTRY(); 162 163 /* Create the generic state object */ 164 165 state = acpi_ut_create_generic_state(); 166 if (!state) { 167 return (NULL); 168 } 169 170 /* Init fields specific to the update struct */ 171 172 state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; 173 state->update.object = object; 174 state->update.value = action; 175 return (state); 176 } 177 178 /******************************************************************************* 179 * 180 * FUNCTION: acpi_ut_create_pkg_state 181 * 182 * PARAMETERS: object - Initial Object to be installed in the state 183 * action - Update action to be performed 184 * 185 * RETURN: New state object, null on failure 186 * 187 * DESCRIPTION: Create a "Package State" 188 * 189 ******************************************************************************/ 190 191 union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, 192 void *external_object, 193 u32 index) 194 { 195 union acpi_generic_state *state; 196 197 ACPI_FUNCTION_ENTRY(); 198 199 /* Create the generic state object */ 200 201 state = acpi_ut_create_generic_state(); 202 if (!state) { 203 return (NULL); 204 } 205 206 /* Init fields specific to the update struct */ 207 208 state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE; 209 state->pkg.source_object = (union acpi_operand_object *)internal_object; 210 state->pkg.dest_object = external_object; 211 state->pkg.index = index; 212 state->pkg.num_packages = 1; 213 214 return (state); 215 } 216 217 /******************************************************************************* 218 * 219 * FUNCTION: acpi_ut_create_control_state 220 * 221 * PARAMETERS: None 222 * 223 * RETURN: New state object, null on failure 224 * 225 * DESCRIPTION: Create a "Control State" - a flavor of the generic state used 226 * to support nested IF/WHILE constructs in the AML. 227 * 228 ******************************************************************************/ 229 230 union acpi_generic_state *acpi_ut_create_control_state(void) 231 { 232 union acpi_generic_state *state; 233 234 ACPI_FUNCTION_ENTRY(); 235 236 /* Create the generic state object */ 237 238 state = acpi_ut_create_generic_state(); 239 if (!state) { 240 return (NULL); 241 } 242 243 /* Init fields specific to the control struct */ 244 245 state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; 246 state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; 247 248 return (state); 249 } 250 251 /******************************************************************************* 252 * 253 * FUNCTION: acpi_ut_delete_generic_state 254 * 255 * PARAMETERS: state - The state object to be deleted 256 * 257 * RETURN: None 258 * 259 * DESCRIPTION: Release a state object to the state cache. NULL state objects 260 * are ignored. 261 * 262 ******************************************************************************/ 263 264 void acpi_ut_delete_generic_state(union acpi_generic_state *state) 265 { 266 ACPI_FUNCTION_ENTRY(); 267 268 /* Ignore null state */ 269 270 if (state) { 271 (void)acpi_os_release_object(acpi_gbl_state_cache, state); 272 } 273 274 return; 275 } 276