diff options
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r-- | drivers/acpi/utilities/utmisc.c | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 89efba7bf449..64dd64b1aa18 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
@@ -64,6 +64,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
64 | { | 64 | { |
65 | acpi_native_uint i; | 65 | acpi_native_uint i; |
66 | acpi_native_uint j; | 66 | acpi_native_uint j; |
67 | acpi_native_uint k; | ||
67 | acpi_status status; | 68 | acpi_status status; |
68 | 69 | ||
69 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); | 70 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); |
@@ -85,32 +86,50 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
85 | 86 | ||
86 | /* | 87 | /* |
87 | * Find a free owner ID, cycle through all possible IDs on repeated | 88 | * Find a free owner ID, cycle through all possible IDs on repeated |
88 | * allocations. Note: Index for next possible ID is equal to the value | 89 | * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have |
89 | * of the last allocated ID. | 90 | * to be scanned twice. |
90 | */ | 91 | */ |
91 | for (i = 0, j = acpi_gbl_last_owner_id; i < 32; i++, j++) { | 92 | for (i = 0, j = acpi_gbl_last_owner_id_index; |
92 | if (j >= 32) { | 93 | i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { |
93 | j = 0; /* Wraparound to ID start */ | 94 | if (j >= ACPI_NUM_OWNERID_MASKS) { |
95 | j = 0; /* Wraparound to start of mask array */ | ||
94 | } | 96 | } |
95 | 97 | ||
96 | if (!(acpi_gbl_owner_id_mask & (1 << j))) { | 98 | for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { |
97 | /* | 99 | if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { |
98 | * Found a free ID. The actual ID is the bit index plus one, | 100 | /* There are no free IDs in this mask */ |
99 | * making zero an invalid Owner ID. Save this as the last ID | ||
100 | * allocated and update the global ID mask. | ||
101 | */ | ||
102 | acpi_gbl_last_owner_id = (acpi_owner_id) (j + 1); | ||
103 | *owner_id = acpi_gbl_last_owner_id; | ||
104 | 101 | ||
105 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, | 102 | break; |
106 | "Current owner_id mask: %8.8X New ID: %2.2X\n", | 103 | } |
107 | acpi_gbl_owner_id_mask, | ||
108 | (unsigned int) | ||
109 | acpi_gbl_last_owner_id)); | ||
110 | 104 | ||
111 | acpi_gbl_owner_id_mask |= (1 << j); | 105 | if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { |
112 | goto exit; | 106 | /* |
107 | * Found a free ID. The actual ID is the bit index plus one, | ||
108 | * making zero an invalid Owner ID. Save this as the last ID | ||
109 | * allocated and update the global ID mask. | ||
110 | */ | ||
111 | acpi_gbl_owner_id_mask[j] |= (1 << k); | ||
112 | |||
113 | acpi_gbl_last_owner_id_index = (u8) j; | ||
114 | acpi_gbl_next_owner_id_offset = (u8) (k + 1); | ||
115 | |||
116 | /* | ||
117 | * Construct encoded ID from the index and bit position | ||
118 | * | ||
119 | * Note: Last [j].k (bit 255) is never used and is marked | ||
120 | * permanently allocated (prevents +1 overflow) | ||
121 | */ | ||
122 | *owner_id = | ||
123 | (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); | ||
124 | |||
125 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, | ||
126 | "Allocated owner_id: %2.2X\n", | ||
127 | (unsigned int)*owner_id)); | ||
128 | goto exit; | ||
129 | } | ||
113 | } | 130 | } |
131 | |||
132 | acpi_gbl_next_owner_id_offset = 0; | ||
114 | } | 133 | } |
115 | 134 | ||
116 | /* | 135 | /* |
@@ -124,7 +143,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
124 | * methods, or there may be a bug where the IDs are not released. | 143 | * methods, or there may be a bug where the IDs are not released. |
125 | */ | 144 | */ |
126 | status = AE_OWNER_ID_LIMIT; | 145 | status = AE_OWNER_ID_LIMIT; |
127 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); | 146 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT\n")); |
128 | 147 | ||
129 | exit: | 148 | exit: |
130 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); | 149 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); |
@@ -141,7 +160,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
141 | * control method or unloading a table. Either way, we would | 160 | * control method or unloading a table. Either way, we would |
142 | * ignore any error anyway. | 161 | * ignore any error anyway. |
143 | * | 162 | * |
144 | * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32 | 163 | * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 |
145 | * | 164 | * |
146 | ******************************************************************************/ | 165 | ******************************************************************************/ |
147 | 166 | ||
@@ -149,6 +168,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
149 | { | 168 | { |
150 | acpi_owner_id owner_id = *owner_id_ptr; | 169 | acpi_owner_id owner_id = *owner_id_ptr; |
151 | acpi_status status; | 170 | acpi_status status; |
171 | acpi_native_uint index; | ||
172 | u32 bit; | ||
152 | 173 | ||
153 | ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); | 174 | ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); |
154 | 175 | ||
@@ -158,7 +179,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
158 | 179 | ||
159 | /* Zero is not a valid owner_iD */ | 180 | /* Zero is not a valid owner_iD */ |
160 | 181 | ||
161 | if ((owner_id == 0) || (owner_id > 32)) { | 182 | if ((owner_id == 0) || (owner_id > 255)) { |
162 | ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); | 183 | ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); |
163 | return_VOID; | 184 | return_VOID; |
164 | } | 185 | } |
@@ -174,10 +195,18 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
174 | 195 | ||
175 | owner_id--; | 196 | owner_id--; |
176 | 197 | ||
198 | /* Decode ID to index/offset pair */ | ||
199 | |||
200 | index = ACPI_DIV_32(owner_id); | ||
201 | bit = 1 << ACPI_MOD_32(owner_id); | ||
202 | |||
177 | /* Free the owner ID only if it is valid */ | 203 | /* Free the owner ID only if it is valid */ |
178 | 204 | ||
179 | if (acpi_gbl_owner_id_mask & (1 << owner_id)) { | 205 | if (acpi_gbl_owner_id_mask[index] & bit) { |
180 | acpi_gbl_owner_id_mask ^= (1 << owner_id); | 206 | acpi_gbl_owner_id_mask[index] ^= bit; |
207 | } else { | ||
208 | ACPI_REPORT_ERROR(("Release of non-allocated owner_id: %2.2X\n", | ||
209 | owner_id + 1)); | ||
181 | } | 210 | } |
182 | 211 | ||
183 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); | 212 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); |