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