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