utownerid.c revision 245582
1244971Sjkim/*******************************************************************************
2244971Sjkim *
3244971Sjkim * Module Name: utownerid - Support for Table/Method Owner IDs
4244971Sjkim *
5244971Sjkim ******************************************************************************/
6244971Sjkim
7244971Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9244971Sjkim * All rights reserved.
10244971Sjkim *
11244971Sjkim * Redistribution and use in source and binary forms, with or without
12244971Sjkim * modification, are permitted provided that the following conditions
13244971Sjkim * are met:
14244971Sjkim * 1. Redistributions of source code must retain the above copyright
15244971Sjkim *    notice, this list of conditions, and the following disclaimer,
16244971Sjkim *    without modification.
17244971Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18244971Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19244971Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20244971Sjkim *    including a substantially similar Disclaimer requirement for further
21244971Sjkim *    binary redistribution.
22244971Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23244971Sjkim *    of any contributors may be used to endorse or promote products derived
24244971Sjkim *    from this software without specific prior written permission.
25244971Sjkim *
26244971Sjkim * Alternatively, this software may be distributed under the terms of the
27244971Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28244971Sjkim * Software Foundation.
29244971Sjkim *
30244971Sjkim * NO WARRANTY
31244971Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32244971Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33244971Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34244971Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35244971Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36244971Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37244971Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38244971Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39244971Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40244971Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41244971Sjkim * POSSIBILITY OF SUCH DAMAGES.
42244971Sjkim */
43244971Sjkim
44244971Sjkim
45244971Sjkim#define __UTOWNERID_C__
46244971Sjkim
47245582Sjkim#include <contrib/dev/acpica/include/acpi.h>
48245582Sjkim#include <contrib/dev/acpica/include/accommon.h>
49245582Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50244971Sjkim
51244971Sjkim
52244971Sjkim#define _COMPONENT          ACPI_UTILITIES
53244971Sjkim        ACPI_MODULE_NAME    ("utownerid")
54244971Sjkim
55244971Sjkim
56244971Sjkim/*******************************************************************************
57244971Sjkim *
58244971Sjkim * FUNCTION:    AcpiUtAllocateOwnerId
59244971Sjkim *
60244971Sjkim * PARAMETERS:  OwnerId         - Where the new owner ID is returned
61244971Sjkim *
62244971Sjkim * RETURN:      Status
63244971Sjkim *
64244971Sjkim * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
65244971Sjkim *              track objects created by the table or method, to be deleted
66244971Sjkim *              when the method exits or the table is unloaded.
67244971Sjkim *
68244971Sjkim ******************************************************************************/
69244971Sjkim
70244971SjkimACPI_STATUS
71244971SjkimAcpiUtAllocateOwnerId (
72244971Sjkim    ACPI_OWNER_ID           *OwnerId)
73244971Sjkim{
74244971Sjkim    UINT32                  i;
75244971Sjkim    UINT32                  j;
76244971Sjkim    UINT32                  k;
77244971Sjkim    ACPI_STATUS             Status;
78244971Sjkim
79244971Sjkim
80244971Sjkim    ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
81244971Sjkim
82244971Sjkim
83244971Sjkim    /* Guard against multiple allocations of ID to the same location */
84244971Sjkim
85244971Sjkim    if (*OwnerId)
86244971Sjkim    {
87244971Sjkim        ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
88244971Sjkim        return_ACPI_STATUS (AE_ALREADY_EXISTS);
89244971Sjkim    }
90244971Sjkim
91244971Sjkim    /* Mutex for the global ID mask */
92244971Sjkim
93244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
94244971Sjkim    if (ACPI_FAILURE (Status))
95244971Sjkim    {
96244971Sjkim        return_ACPI_STATUS (Status);
97244971Sjkim    }
98244971Sjkim
99244971Sjkim    /*
100244971Sjkim     * Find a free owner ID, cycle through all possible IDs on repeated
101244971Sjkim     * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
102244971Sjkim     * to be scanned twice.
103244971Sjkim     */
104244971Sjkim    for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
105244971Sjkim         i < (ACPI_NUM_OWNERID_MASKS + 1);
106244971Sjkim         i++, j++)
107244971Sjkim    {
108244971Sjkim        if (j >= ACPI_NUM_OWNERID_MASKS)
109244971Sjkim        {
110244971Sjkim            j = 0;  /* Wraparound to start of mask array */
111244971Sjkim        }
112244971Sjkim
113244971Sjkim        for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
114244971Sjkim        {
115244971Sjkim            if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
116244971Sjkim            {
117244971Sjkim                /* There are no free IDs in this mask */
118244971Sjkim
119244971Sjkim                break;
120244971Sjkim            }
121244971Sjkim
122244971Sjkim            if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
123244971Sjkim            {
124244971Sjkim                /*
125244971Sjkim                 * Found a free ID. The actual ID is the bit index plus one,
126244971Sjkim                 * making zero an invalid Owner ID. Save this as the last ID
127244971Sjkim                 * allocated and update the global ID mask.
128244971Sjkim                 */
129244971Sjkim                AcpiGbl_OwnerIdMask[j] |= (1 << k);
130244971Sjkim
131244971Sjkim                AcpiGbl_LastOwnerIdIndex = (UINT8) j;
132244971Sjkim                AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
133244971Sjkim
134244971Sjkim                /*
135244971Sjkim                 * Construct encoded ID from the index and bit position
136244971Sjkim                 *
137244971Sjkim                 * Note: Last [j].k (bit 255) is never used and is marked
138244971Sjkim                 * permanently allocated (prevents +1 overflow)
139244971Sjkim                 */
140244971Sjkim                *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
141244971Sjkim
142244971Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
143244971Sjkim                    "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
144244971Sjkim                goto Exit;
145244971Sjkim            }
146244971Sjkim        }
147244971Sjkim
148244971Sjkim        AcpiGbl_NextOwnerIdOffset = 0;
149244971Sjkim    }
150244971Sjkim
151244971Sjkim    /*
152244971Sjkim     * All OwnerIds have been allocated. This typically should
153244971Sjkim     * not happen since the IDs are reused after deallocation. The IDs are
154244971Sjkim     * allocated upon table load (one per table) and method execution, and
155244971Sjkim     * they are released when a table is unloaded or a method completes
156244971Sjkim     * execution.
157244971Sjkim     *
158244971Sjkim     * If this error happens, there may be very deep nesting of invoked control
159244971Sjkim     * methods, or there may be a bug where the IDs are not released.
160244971Sjkim     */
161244971Sjkim    Status = AE_OWNER_ID_LIMIT;
162244971Sjkim    ACPI_ERROR ((AE_INFO,
163244971Sjkim        "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
164244971Sjkim
165244971SjkimExit:
166244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
167244971Sjkim    return_ACPI_STATUS (Status);
168244971Sjkim}
169244971Sjkim
170244971Sjkim
171244971Sjkim/*******************************************************************************
172244971Sjkim *
173244971Sjkim * FUNCTION:    AcpiUtReleaseOwnerId
174244971Sjkim *
175244971Sjkim * PARAMETERS:  OwnerIdPtr          - Pointer to a previously allocated OwnerID
176244971Sjkim *
177244971Sjkim * RETURN:      None. No error is returned because we are either exiting a
178244971Sjkim *              control method or unloading a table. Either way, we would
179244971Sjkim *              ignore any error anyway.
180244971Sjkim *
181244971Sjkim * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
182244971Sjkim *
183244971Sjkim ******************************************************************************/
184244971Sjkim
185244971Sjkimvoid
186244971SjkimAcpiUtReleaseOwnerId (
187244971Sjkim    ACPI_OWNER_ID           *OwnerIdPtr)
188244971Sjkim{
189244971Sjkim    ACPI_OWNER_ID           OwnerId = *OwnerIdPtr;
190244971Sjkim    ACPI_STATUS             Status;
191244971Sjkim    UINT32                  Index;
192244971Sjkim    UINT32                  Bit;
193244971Sjkim
194244971Sjkim
195244971Sjkim    ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
196244971Sjkim
197244971Sjkim
198244971Sjkim    /* Always clear the input OwnerId (zero is an invalid ID) */
199244971Sjkim
200244971Sjkim    *OwnerIdPtr = 0;
201244971Sjkim
202244971Sjkim    /* Zero is not a valid OwnerID */
203244971Sjkim
204244971Sjkim    if (OwnerId == 0)
205244971Sjkim    {
206244971Sjkim        ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
207244971Sjkim        return_VOID;
208244971Sjkim    }
209244971Sjkim
210244971Sjkim    /* Mutex for the global ID mask */
211244971Sjkim
212244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
213244971Sjkim    if (ACPI_FAILURE (Status))
214244971Sjkim    {
215244971Sjkim        return_VOID;
216244971Sjkim    }
217244971Sjkim
218244971Sjkim    /* Normalize the ID to zero */
219244971Sjkim
220244971Sjkim    OwnerId--;
221244971Sjkim
222244971Sjkim    /* Decode ID to index/offset pair */
223244971Sjkim
224244971Sjkim    Index = ACPI_DIV_32 (OwnerId);
225244971Sjkim    Bit = 1 << ACPI_MOD_32 (OwnerId);
226244971Sjkim
227244971Sjkim    /* Free the owner ID only if it is valid */
228244971Sjkim
229244971Sjkim    if (AcpiGbl_OwnerIdMask[Index] & Bit)
230244971Sjkim    {
231244971Sjkim        AcpiGbl_OwnerIdMask[Index] ^= Bit;
232244971Sjkim    }
233244971Sjkim    else
234244971Sjkim    {
235244971Sjkim        ACPI_ERROR ((AE_INFO,
236244971Sjkim            "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
237244971Sjkim    }
238244971Sjkim
239244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
240244971Sjkim    return_VOID;
241244971Sjkim}
242