diff options
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r-- | drivers/acpi/utilities/utmisc.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2a9110c06391..89efba7bf449 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
@@ -63,6 +63,7 @@ ACPI_MODULE_NAME("utmisc") | |||
63 | acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | 63 | 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_status status; | 67 | acpi_status status; |
67 | 68 | ||
68 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); | 69 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); |
@@ -82,29 +83,46 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
82 | return_ACPI_STATUS(status); | 83 | return_ACPI_STATUS(status); |
83 | } | 84 | } |
84 | 85 | ||
85 | /* Find a free owner ID */ | 86 | /* |
87 | * 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 | * of the last allocated ID. | ||
90 | */ | ||
91 | for (i = 0, j = acpi_gbl_last_owner_id; i < 32; i++, j++) { | ||
92 | if (j >= 32) { | ||
93 | j = 0; /* Wraparound to ID start */ | ||
94 | } | ||
95 | |||
96 | if (!(acpi_gbl_owner_id_mask & (1 << j))) { | ||
97 | /* | ||
98 | * Found a free ID. The actual ID is the bit index plus one, | ||
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; | ||
86 | 104 | ||
87 | for (i = 0; i < 32; i++) { | ||
88 | if (!(acpi_gbl_owner_id_mask & (1 << i))) { | ||
89 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, | 105 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, |
90 | "Current owner_id mask: %8.8X New ID: %2.2X\n", | 106 | "Current owner_id mask: %8.8X New ID: %2.2X\n", |
91 | acpi_gbl_owner_id_mask, | 107 | acpi_gbl_owner_id_mask, |
92 | (unsigned int)(i + 1))); | 108 | (unsigned int) |
109 | acpi_gbl_last_owner_id)); | ||
93 | 110 | ||
94 | acpi_gbl_owner_id_mask |= (1 << i); | 111 | acpi_gbl_owner_id_mask |= (1 << j); |
95 | *owner_id = (acpi_owner_id) (i + 1); | ||
96 | goto exit; | 112 | goto exit; |
97 | } | 113 | } |
98 | } | 114 | } |
99 | 115 | ||
100 | /* | 116 | /* |
101 | * If we are here, all owner_ids have been allocated. This probably should | 117 | * All owner_ids have been allocated. This typically should |
102 | * not happen since the IDs are reused after deallocation. The IDs are | 118 | * not happen since the IDs are reused after deallocation. The IDs are |
103 | * allocated upon table load (one per table) and method execution, and | 119 | * allocated upon table load (one per table) and method execution, and |
104 | * they are released when a table is unloaded or a method completes | 120 | * they are released when a table is unloaded or a method completes |
105 | * execution. | 121 | * execution. |
122 | * | ||
123 | * If this error happens, there may be very deep nesting of invoked control | ||
124 | * methods, or there may be a bug where the IDs are not released. | ||
106 | */ | 125 | */ |
107 | *owner_id = 0; | ||
108 | status = AE_OWNER_ID_LIMIT; | 126 | status = AE_OWNER_ID_LIMIT; |
109 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); | 127 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); |
110 | 128 | ||