summaryrefslogtreecommitdiff
path: root/drivers/acpi/utilities/utmisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r--drivers/acpi/utilities/utmisc.c79
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)
{
acpi_native_uint i;
acpi_native_uint j;
+ acpi_native_uint k;
acpi_status status;
ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
@@ -85,32 +86,50 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
/*
* Find a free owner ID, cycle through all possible IDs on repeated
- * allocations. Note: Index for next possible ID is equal to the value
- * of the last allocated ID.
+ * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
+ * to be scanned twice.
*/
- for (i = 0, j = acpi_gbl_last_owner_id; i < 32; i++, j++) {
- if (j >= 32) {
- j = 0; /* Wraparound to ID start */
+ for (i = 0, j = acpi_gbl_last_owner_id_index;
+ i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
+ if (j >= ACPI_NUM_OWNERID_MASKS) {
+ j = 0; /* Wraparound to start of mask array */
}
- if (!(acpi_gbl_owner_id_mask & (1 << j))) {
- /*
- * Found a free ID. The actual ID is the bit index plus one,
- * making zero an invalid Owner ID. Save this as the last ID
- * allocated and update the global ID mask.
- */
- acpi_gbl_last_owner_id = (acpi_owner_id) (j + 1);
- *owner_id = acpi_gbl_last_owner_id;
+ for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
+ if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
+ /* There are no free IDs in this mask */
- ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
- "Current owner_id mask: %8.8X New ID: %2.2X\n",
- acpi_gbl_owner_id_mask,
- (unsigned int)
- acpi_gbl_last_owner_id));
+ break;
+ }
- acpi_gbl_owner_id_mask |= (1 << j);
- goto exit;
+ if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) {
+ /*
+ * Found a free ID. The actual ID is the bit index plus one,
+ * making zero an invalid Owner ID. Save this as the last ID
+ * allocated and update the global ID mask.
+ */
+ acpi_gbl_owner_id_mask[j] |= (1 << k);
+
+ acpi_gbl_last_owner_id_index = (u8) j;
+ acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+
+ /*
+ * Construct encoded ID from the index and bit position
+ *
+ * Note: Last [j].k (bit 255) is never used and is marked
+ * permanently allocated (prevents +1 overflow)
+ */
+ *owner_id =
+ (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
+
+ ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
+ "Allocated owner_id: %2.2X\n",
+ (unsigned int)*owner_id));
+ goto exit;
+ }
}
+
+ acpi_gbl_next_owner_id_offset = 0;
}
/*
@@ -124,7 +143,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
* methods, or there may be a bug where the IDs are not released.
*/
status = AE_OWNER_ID_LIMIT;
- ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
+ ACPI_REPORT_ERROR(("Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT\n"));
exit:
(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -141,7 +160,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
* control method or unloading a table. Either way, we would
* ignore any error anyway.
*
- * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
*
******************************************************************************/
@@ -149,6 +168,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
{
acpi_owner_id owner_id = *owner_id_ptr;
acpi_status status;
+ acpi_native_uint index;
+ u32 bit;
ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
@@ -158,7 +179,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
/* Zero is not a valid owner_iD */
- if ((owner_id == 0) || (owner_id > 32)) {
+ if ((owner_id == 0) || (owner_id > 255)) {
ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
return_VOID;
}
@@ -174,10 +195,18 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
owner_id--;
+ /* Decode ID to index/offset pair */
+
+ index = ACPI_DIV_32(owner_id);
+ bit = 1 << ACPI_MOD_32(owner_id);
+
/* Free the owner ID only if it is valid */
- if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
- acpi_gbl_owner_id_mask ^= (1 << owner_id);
+ if (acpi_gbl_owner_id_mask[index] & bit) {
+ acpi_gbl_owner_id_mask[index] ^= bit;
+ } else {
+ ACPI_REPORT_ERROR(("Release of non-allocated owner_id: %2.2X\n",
+ owner_id + 1));
}
(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);