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) { 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); |