1 /*******************************************************************************
   2  *
   3  * Module Name: utownerid - Support for Table/Method Owner IDs
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #define __UTOWNERID_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acnamesp.h"
  50 
  51 
  52 #define _COMPONENT          ACPI_UTILITIES
  53         ACPI_MODULE_NAME    ("utownerid")
  54 
  55 
  56 /*******************************************************************************
  57  *
  58  * FUNCTION:    AcpiUtAllocateOwnerId
  59  *
  60  * PARAMETERS:  OwnerId         - Where the new owner ID is returned
  61  *
  62  * RETURN:      Status
  63  *
  64  * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
  65  *              track objects created by the table or method, to be deleted
  66  *              when the method exits or the table is unloaded.
  67  *
  68  ******************************************************************************/
  69 
  70 ACPI_STATUS
  71 AcpiUtAllocateOwnerId (
  72     ACPI_OWNER_ID           *OwnerId)
  73 {
  74     UINT32                  i;
  75     UINT32                  j;
  76     UINT32                  k;
  77     ACPI_STATUS             Status;
  78 
  79 
  80     ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
  81 
  82 
  83     /* Guard against multiple allocations of ID to the same location */
  84 
  85     if (*OwnerId)
  86     {
  87         ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
  88         return_ACPI_STATUS (AE_ALREADY_EXISTS);
  89     }
  90 
  91     /* Mutex for the global ID mask */
  92 
  93     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
  94     if (ACPI_FAILURE (Status))
  95     {
  96         return_ACPI_STATUS (Status);
  97     }
  98 
  99     /*
 100      * Find a free owner ID, cycle through all possible IDs on repeated
 101      * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
 102      * to be scanned twice.
 103      */
 104     for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
 105          i < (ACPI_NUM_OWNERID_MASKS + 1);
 106          i++, j++)
 107     {
 108         if (j >= ACPI_NUM_OWNERID_MASKS)
 109         {
 110             j = 0;  /* Wraparound to start of mask array */
 111         }
 112 
 113         for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
 114         {
 115             if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
 116             {
 117                 /* There are no free IDs in this mask */
 118 
 119                 break;
 120             }
 121 
 122             if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
 123             {
 124                 /*
 125                  * Found a free ID. The actual ID is the bit index plus one,
 126                  * making zero an invalid Owner ID. Save this as the last ID
 127                  * allocated and update the global ID mask.
 128                  */
 129                 AcpiGbl_OwnerIdMask[j] |= (1 << k);
 130 
 131                 AcpiGbl_LastOwnerIdIndex = (UINT8) j;
 132                 AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
 133 
 134                 /*
 135                  * Construct encoded ID from the index and bit position
 136                  *
 137                  * Note: Last [j].k (bit 255) is never used and is marked
 138                  * permanently allocated (prevents +1 overflow)
 139                  */
 140                 *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
 141 
 142                 ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
 143                     "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
 144                 goto Exit;
 145             }
 146         }
 147 
 148         AcpiGbl_NextOwnerIdOffset = 0;
 149     }
 150 
 151     /*
 152      * All OwnerIds have been allocated. This typically should
 153      * not happen since the IDs are reused after deallocation. The IDs are
 154      * allocated upon table load (one per table) and method execution, and
 155      * they are released when a table is unloaded or a method completes
 156      * execution.
 157      *
 158      * If this error happens, there may be very deep nesting of invoked control
 159      * methods, or there may be a bug where the IDs are not released.
 160      */
 161     Status = AE_OWNER_ID_LIMIT;
 162     ACPI_ERROR ((AE_INFO,
 163         "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
 164 
 165 Exit:
 166     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
 167     return_ACPI_STATUS (Status);
 168 }
 169 
 170 
 171 /*******************************************************************************
 172  *
 173  * FUNCTION:    AcpiUtReleaseOwnerId
 174  *
 175  * PARAMETERS:  OwnerIdPtr          - Pointer to a previously allocated OwnerID
 176  *
 177  * RETURN:      None. No error is returned because we are either exiting a
 178  *              control method or unloading a table. Either way, we would
 179  *              ignore any error anyway.
 180  *
 181  * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
 182  *
 183  ******************************************************************************/
 184 
 185 void
 186 AcpiUtReleaseOwnerId (
 187     ACPI_OWNER_ID           *OwnerIdPtr)
 188 {
 189     ACPI_OWNER_ID           OwnerId = *OwnerIdPtr;
 190     ACPI_STATUS             Status;
 191     UINT32                  Index;
 192     UINT32                  Bit;
 193 
 194 
 195     ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
 196 
 197 
 198     /* Always clear the input OwnerId (zero is an invalid ID) */
 199 
 200     *OwnerIdPtr = 0;
 201 
 202     /* Zero is not a valid OwnerID */
 203 
 204     if (OwnerId == 0)
 205     {
 206         ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
 207         return_VOID;
 208     }
 209 
 210     /* Mutex for the global ID mask */
 211 
 212     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
 213     if (ACPI_FAILURE (Status))
 214     {
 215         return_VOID;
 216     }
 217 
 218     /* Normalize the ID to zero */
 219 
 220     OwnerId--;
 221 
 222     /* Decode ID to index/offset pair */
 223 
 224     Index = ACPI_DIV_32 (OwnerId);
 225     Bit = 1 << ACPI_MOD_32 (OwnerId);
 226 
 227     /* Free the owner ID only if it is valid */
 228 
 229     if (AcpiGbl_OwnerIdMask[Index] & Bit)
 230     {
 231         AcpiGbl_OwnerIdMask[Index] ^= Bit;
 232     }
 233     else
 234     {
 235         ACPI_ERROR ((AE_INFO,
 236             "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
 237     }
 238 
 239     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
 240     return_VOID;
 241 }