Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/*******************************************************************************
  3 *
  4 * Module Name: utownerid - Support for Table/Method Owner IDs
  5 *
  6 ******************************************************************************/
  7
  8#include <acpi/acpi.h>
  9#include "accommon.h"
 10#include "acnamesp.h"
 11
 12#define _COMPONENT          ACPI_UTILITIES
 13ACPI_MODULE_NAME("utownerid")
 14
 15/*******************************************************************************
 16 *
 17 * FUNCTION:    acpi_ut_allocate_owner_id
 18 *
 19 * PARAMETERS:  owner_id        - Where the new owner ID is returned
 20 *
 21 * RETURN:      Status
 22 *
 23 * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
 24 *              track objects created by the table or method, to be deleted
 25 *              when the method exits or the table is unloaded.
 26 *
 27 ******************************************************************************/
 28acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
 29{
 30	u32 i;
 31	u32 j;
 32	u32 k;
 33	acpi_status status;
 34
 35	ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
 36
 37	/* Guard against multiple allocations of ID to the same location */
 38
 39	if (*owner_id) {
 40		ACPI_ERROR((AE_INFO,
 41			    "Owner ID [0x%3.3X] already exists", *owner_id));
 42		return_ACPI_STATUS(AE_ALREADY_EXISTS);
 43	}
 44
 45	/* Mutex for the global ID mask */
 46
 47	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
 48	if (ACPI_FAILURE(status)) {
 49		return_ACPI_STATUS(status);
 50	}
 51
 52	/*
 53	 * Find a free owner ID, cycle through all possible IDs on repeated
 54	 * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
 55	 * may have to be scanned twice.
 56	 */
 57	for (i = 0, j = acpi_gbl_last_owner_id_index;
 58	     i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
 59		if (j >= ACPI_NUM_OWNERID_MASKS) {
 60			j = 0;	/* Wraparound to start of mask array */
 61		}
 62
 63		for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
 64			if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
 65
 66				/* There are no free IDs in this mask */
 67
 68				break;
 69			}
 70
 71			/*
 72			 * Note: the u32 cast ensures that 1 is stored as a unsigned
 73			 * integer. Omitting the cast may result in 1 being stored as an
 74			 * int. Some compilers or runtime error detection may flag this as
 75			 * an error.
 76			 */
 77			if (!(acpi_gbl_owner_id_mask[j] & ((u32)1 << k))) {
 78				/*
 79				 * Found a free ID. The actual ID is the bit index plus one,
 80				 * making zero an invalid Owner ID. Save this as the last ID
 81				 * allocated and update the global ID mask.
 82				 */
 83				acpi_gbl_owner_id_mask[j] |= ((u32)1 << k);
 84
 85				acpi_gbl_last_owner_id_index = (u8)j;
 86				acpi_gbl_next_owner_id_offset = (u8)(k + 1);
 87
 88				/*
 89				 * Construct encoded ID from the index and bit position
 90				 *
 91				 * Note: Last [j].k (bit 4095) is never used and is marked
 92				 * permanently allocated (prevents +1 overflow)
 93				 */
 94				*owner_id =
 95				    (acpi_owner_id)((k + 1) + ACPI_MUL_32(j));
 96
 97				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
 98						  "Allocated OwnerId: 0x%3.3X\n",
 99						  (unsigned int)*owner_id));
100				goto exit;
101			}
102		}
103
104		acpi_gbl_next_owner_id_offset = 0;
105	}
106
107	/*
108	 * All owner_ids have been allocated. This typically should
109	 * not happen since the IDs are reused after deallocation. The IDs are
110	 * allocated upon table load (one per table) and method execution, and
111	 * they are released when a table is unloaded or a method completes
112	 * execution.
113	 *
114	 * If this error happens, there may be very deep nesting of invoked
115	 * control methods, or there may be a bug where the IDs are not released.
116	 */
117	status = AE_OWNER_ID_LIMIT;
118	ACPI_ERROR((AE_INFO,
119		    "Could not allocate new OwnerId (4095 max), AE_OWNER_ID_LIMIT"));
120
121exit:
122	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
123	return_ACPI_STATUS(status);
124}
125
126/*******************************************************************************
127 *
128 * FUNCTION:    acpi_ut_release_owner_id
129 *
130 * PARAMETERS:  owner_id_ptr        - Pointer to a previously allocated owner_ID
131 *
132 * RETURN:      None. No error is returned because we are either exiting a
133 *              control method or unloading a table. Either way, we would
134 *              ignore any error anyway.
135 *
136 * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
137 *
138 ******************************************************************************/
139
140void acpi_ut_release_owner_id(acpi_owner_id *owner_id_ptr)
141{
142	acpi_owner_id owner_id = *owner_id_ptr;
143	acpi_status status;
144	u32 index;
145	u32 bit;
146
147	ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
148
149	/* Always clear the input owner_id (zero is an invalid ID) */
150
151	*owner_id_ptr = 0;
152
153	/* Zero is not a valid owner_ID */
154
155	if (owner_id == 0) {
156		ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%3.3X", owner_id));
157		return_VOID;
158	}
159
160	/* Mutex for the global ID mask */
161
162	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
163	if (ACPI_FAILURE(status)) {
164		return_VOID;
165	}
166
167	/* Normalize the ID to zero */
168
169	owner_id--;
170
171	/* Decode ID to index/offset pair */
172
173	index = ACPI_DIV_32(owner_id);
174	bit = (u32)1 << ACPI_MOD_32(owner_id);
175
176	/* Free the owner ID only if it is valid */
177
178	if (acpi_gbl_owner_id_mask[index] & bit) {
179		acpi_gbl_owner_id_mask[index] ^= bit;
180	} else {
181		ACPI_ERROR((AE_INFO,
182			    "Attempted release of non-allocated OwnerId: 0x%3.3X",
183			    owner_id + 1));
184	}
185
186	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
187	return_VOID;
188}
v5.14.15
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/*******************************************************************************
  3 *
  4 * Module Name: utownerid - Support for Table/Method Owner IDs
  5 *
  6 ******************************************************************************/
  7
  8#include <acpi/acpi.h>
  9#include "accommon.h"
 10#include "acnamesp.h"
 11
 12#define _COMPONENT          ACPI_UTILITIES
 13ACPI_MODULE_NAME("utownerid")
 14
 15/*******************************************************************************
 16 *
 17 * FUNCTION:    acpi_ut_allocate_owner_id
 18 *
 19 * PARAMETERS:  owner_id        - Where the new owner ID is returned
 20 *
 21 * RETURN:      Status
 22 *
 23 * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
 24 *              track objects created by the table or method, to be deleted
 25 *              when the method exits or the table is unloaded.
 26 *
 27 ******************************************************************************/
 28acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
 29{
 30	u32 i;
 31	u32 j;
 32	u32 k;
 33	acpi_status status;
 34
 35	ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
 36
 37	/* Guard against multiple allocations of ID to the same location */
 38
 39	if (*owner_id) {
 40		ACPI_ERROR((AE_INFO,
 41			    "Owner ID [0x%3.3X] already exists", *owner_id));
 42		return_ACPI_STATUS(AE_ALREADY_EXISTS);
 43	}
 44
 45	/* Mutex for the global ID mask */
 46
 47	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
 48	if (ACPI_FAILURE(status)) {
 49		return_ACPI_STATUS(status);
 50	}
 51
 52	/*
 53	 * Find a free owner ID, cycle through all possible IDs on repeated
 54	 * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
 55	 * may have to be scanned twice.
 56	 */
 57	for (i = 0, j = acpi_gbl_last_owner_id_index;
 58	     i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
 59		if (j >= ACPI_NUM_OWNERID_MASKS) {
 60			j = 0;	/* Wraparound to start of mask array */
 61		}
 62
 63		for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
 64			if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
 65
 66				/* There are no free IDs in this mask */
 67
 68				break;
 69			}
 70
 71			/*
 72			 * Note: the u32 cast ensures that 1 is stored as a unsigned
 73			 * integer. Omitting the cast may result in 1 being stored as an
 74			 * int. Some compilers or runtime error detection may flag this as
 75			 * an error.
 76			 */
 77			if (!(acpi_gbl_owner_id_mask[j] & ((u32)1 << k))) {
 78				/*
 79				 * Found a free ID. The actual ID is the bit index plus one,
 80				 * making zero an invalid Owner ID. Save this as the last ID
 81				 * allocated and update the global ID mask.
 82				 */
 83				acpi_gbl_owner_id_mask[j] |= ((u32)1 << k);
 84
 85				acpi_gbl_last_owner_id_index = (u8)j;
 86				acpi_gbl_next_owner_id_offset = (u8)(k + 1);
 87
 88				/*
 89				 * Construct encoded ID from the index and bit position
 90				 *
 91				 * Note: Last [j].k (bit 4095) is never used and is marked
 92				 * permanently allocated (prevents +1 overflow)
 93				 */
 94				*owner_id =
 95				    (acpi_owner_id)((k + 1) + ACPI_MUL_32(j));
 96
 97				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
 98						  "Allocated OwnerId: 0x%3.3X\n",
 99						  (unsigned int)*owner_id));
100				goto exit;
101			}
102		}
103
104		acpi_gbl_next_owner_id_offset = 0;
105	}
106
107	/*
108	 * All owner_ids have been allocated. This typically should
109	 * not happen since the IDs are reused after deallocation. The IDs are
110	 * allocated upon table load (one per table) and method execution, and
111	 * they are released when a table is unloaded or a method completes
112	 * execution.
113	 *
114	 * If this error happens, there may be very deep nesting of invoked
115	 * control methods, or there may be a bug where the IDs are not released.
116	 */
117	status = AE_OWNER_ID_LIMIT;
118	ACPI_ERROR((AE_INFO,
119		    "Could not allocate new OwnerId (4095 max), AE_OWNER_ID_LIMIT"));
120
121exit:
122	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
123	return_ACPI_STATUS(status);
124}
125
126/*******************************************************************************
127 *
128 * FUNCTION:    acpi_ut_release_owner_id
129 *
130 * PARAMETERS:  owner_id_ptr        - Pointer to a previously allocated owner_ID
131 *
132 * RETURN:      None. No error is returned because we are either exiting a
133 *              control method or unloading a table. Either way, we would
134 *              ignore any error anyway.
135 *
136 * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
137 *
138 ******************************************************************************/
139
140void acpi_ut_release_owner_id(acpi_owner_id *owner_id_ptr)
141{
142	acpi_owner_id owner_id = *owner_id_ptr;
143	acpi_status status;
144	u32 index;
145	u32 bit;
146
147	ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
148
149	/* Always clear the input owner_id (zero is an invalid ID) */
150
151	*owner_id_ptr = 0;
152
153	/* Zero is not a valid owner_ID */
154
155	if (owner_id == 0) {
156		ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%3.3X", owner_id));
157		return_VOID;
158	}
159
160	/* Mutex for the global ID mask */
161
162	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
163	if (ACPI_FAILURE(status)) {
164		return_VOID;
165	}
166
167	/* Normalize the ID to zero */
168
169	owner_id--;
170
171	/* Decode ID to index/offset pair */
172
173	index = ACPI_DIV_32(owner_id);
174	bit = (u32)1 << ACPI_MOD_32(owner_id);
175
176	/* Free the owner ID only if it is valid */
177
178	if (acpi_gbl_owner_id_mask[index] & bit) {
179		acpi_gbl_owner_id_mask[index] ^= bit;
180	} else {
181		ACPI_ERROR((AE_INFO,
182			    "Attempted release of non-allocated OwnerId: 0x%3.3X",
183			    owner_id + 1));
184	}
185
186	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
187	return_VOID;
188}