1244971Sjkim/*******************************************************************************
2244971Sjkim *
3244971Sjkim * Module Name: utownerid - Support for Table/Method Owner IDs
4244971Sjkim *
5244971Sjkim ******************************************************************************/
6244971Sjkim
7244971Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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
44245582Sjkim#include <contrib/dev/acpica/include/acpi.h>
45245582Sjkim#include <contrib/dev/acpica/include/accommon.h>
46245582Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
47244971Sjkim
48244971Sjkim
49244971Sjkim#define _COMPONENT          ACPI_UTILITIES
50244971Sjkim        ACPI_MODULE_NAME    ("utownerid")
51244971Sjkim
52244971Sjkim
53244971Sjkim/*******************************************************************************
54244971Sjkim *
55244971Sjkim * FUNCTION:    AcpiUtAllocateOwnerId
56244971Sjkim *
57244971Sjkim * PARAMETERS:  OwnerId         - Where the new owner ID is returned
58244971Sjkim *
59244971Sjkim * RETURN:      Status
60244971Sjkim *
61244971Sjkim * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
62244971Sjkim *              track objects created by the table or method, to be deleted
63244971Sjkim *              when the method exits or the table is unloaded.
64244971Sjkim *
65244971Sjkim ******************************************************************************/
66244971Sjkim
67244971SjkimACPI_STATUS
68244971SjkimAcpiUtAllocateOwnerId (
69244971Sjkim    ACPI_OWNER_ID           *OwnerId)
70244971Sjkim{
71244971Sjkim    UINT32                  i;
72244971Sjkim    UINT32                  j;
73244971Sjkim    UINT32                  k;
74244971Sjkim    ACPI_STATUS             Status;
75244971Sjkim
76244971Sjkim
77244971Sjkim    ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
78244971Sjkim
79244971Sjkim
80244971Sjkim    /* Guard against multiple allocations of ID to the same location */
81244971Sjkim
82244971Sjkim    if (*OwnerId)
83244971Sjkim    {
84306536Sjkim        ACPI_ERROR ((AE_INFO,
85306536Sjkim            "Owner ID [0x%2.2X] already exists", *OwnerId));
86244971Sjkim        return_ACPI_STATUS (AE_ALREADY_EXISTS);
87244971Sjkim    }
88244971Sjkim
89244971Sjkim    /* Mutex for the global ID mask */
90244971Sjkim
91244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
92244971Sjkim    if (ACPI_FAILURE (Status))
93244971Sjkim    {
94244971Sjkim        return_ACPI_STATUS (Status);
95244971Sjkim    }
96244971Sjkim
97244971Sjkim    /*
98244971Sjkim     * Find a free owner ID, cycle through all possible IDs on repeated
99306536Sjkim     * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
100306536Sjkim     * may have to be scanned twice.
101244971Sjkim     */
102244971Sjkim    for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
103244971Sjkim         i < (ACPI_NUM_OWNERID_MASKS + 1);
104244971Sjkim         i++, j++)
105244971Sjkim    {
106244971Sjkim        if (j >= ACPI_NUM_OWNERID_MASKS)
107244971Sjkim        {
108244971Sjkim            j = 0;  /* Wraparound to start of mask array */
109244971Sjkim        }
110244971Sjkim
111244971Sjkim        for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
112244971Sjkim        {
113244971Sjkim            if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
114244971Sjkim            {
115244971Sjkim                /* There are no free IDs in this mask */
116244971Sjkim
117244971Sjkim                break;
118244971Sjkim            }
119244971Sjkim
120244971Sjkim            if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
121244971Sjkim            {
122244971Sjkim                /*
123244971Sjkim                 * Found a free ID. The actual ID is the bit index plus one,
124244971Sjkim                 * making zero an invalid Owner ID. Save this as the last ID
125244971Sjkim                 * allocated and update the global ID mask.
126244971Sjkim                 */
127244971Sjkim                AcpiGbl_OwnerIdMask[j] |= (1 << k);
128244971Sjkim
129244971Sjkim                AcpiGbl_LastOwnerIdIndex = (UINT8) j;
130244971Sjkim                AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
131244971Sjkim
132244971Sjkim                /*
133244971Sjkim                 * Construct encoded ID from the index and bit position
134244971Sjkim                 *
135244971Sjkim                 * Note: Last [j].k (bit 255) is never used and is marked
136244971Sjkim                 * permanently allocated (prevents +1 overflow)
137244971Sjkim                 */
138244971Sjkim                *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
139244971Sjkim
140244971Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
141244971Sjkim                    "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
142244971Sjkim                goto Exit;
143244971Sjkim            }
144244971Sjkim        }
145244971Sjkim
146244971Sjkim        AcpiGbl_NextOwnerIdOffset = 0;
147244971Sjkim    }
148244971Sjkim
149244971Sjkim    /*
150244971Sjkim     * All OwnerIds have been allocated. This typically should
151244971Sjkim     * not happen since the IDs are reused after deallocation. The IDs are
152244971Sjkim     * allocated upon table load (one per table) and method execution, and
153244971Sjkim     * they are released when a table is unloaded or a method completes
154244971Sjkim     * execution.
155244971Sjkim     *
156306536Sjkim     * If this error happens, there may be very deep nesting of invoked
157306536Sjkim     * control methods, or there may be a bug where the IDs are not released.
158244971Sjkim     */
159244971Sjkim    Status = AE_OWNER_ID_LIMIT;
160244971Sjkim    ACPI_ERROR ((AE_INFO,
161244971Sjkim        "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
162244971Sjkim
163244971SjkimExit:
164244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
165244971Sjkim    return_ACPI_STATUS (Status);
166244971Sjkim}
167244971Sjkim
168244971Sjkim
169244971Sjkim/*******************************************************************************
170244971Sjkim *
171244971Sjkim * FUNCTION:    AcpiUtReleaseOwnerId
172244971Sjkim *
173244971Sjkim * PARAMETERS:  OwnerIdPtr          - Pointer to a previously allocated OwnerID
174244971Sjkim *
175244971Sjkim * RETURN:      None. No error is returned because we are either exiting a
176244971Sjkim *              control method or unloading a table. Either way, we would
177244971Sjkim *              ignore any error anyway.
178244971Sjkim *
179244971Sjkim * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
180244971Sjkim *
181244971Sjkim ******************************************************************************/
182244971Sjkim
183244971Sjkimvoid
184244971SjkimAcpiUtReleaseOwnerId (
185244971Sjkim    ACPI_OWNER_ID           *OwnerIdPtr)
186244971Sjkim{
187244971Sjkim    ACPI_OWNER_ID           OwnerId = *OwnerIdPtr;
188244971Sjkim    ACPI_STATUS             Status;
189244971Sjkim    UINT32                  Index;
190244971Sjkim    UINT32                  Bit;
191244971Sjkim
192244971Sjkim
193244971Sjkim    ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
194244971Sjkim
195244971Sjkim
196244971Sjkim    /* Always clear the input OwnerId (zero is an invalid ID) */
197244971Sjkim
198244971Sjkim    *OwnerIdPtr = 0;
199244971Sjkim
200244971Sjkim    /* Zero is not a valid OwnerID */
201244971Sjkim
202244971Sjkim    if (OwnerId == 0)
203244971Sjkim    {
204244971Sjkim        ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
205244971Sjkim        return_VOID;
206244971Sjkim    }
207244971Sjkim
208244971Sjkim    /* Mutex for the global ID mask */
209244971Sjkim
210244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
211244971Sjkim    if (ACPI_FAILURE (Status))
212244971Sjkim    {
213244971Sjkim        return_VOID;
214244971Sjkim    }
215244971Sjkim
216244971Sjkim    /* Normalize the ID to zero */
217244971Sjkim
218244971Sjkim    OwnerId--;
219244971Sjkim
220244971Sjkim    /* Decode ID to index/offset pair */
221244971Sjkim
222244971Sjkim    Index = ACPI_DIV_32 (OwnerId);
223244971Sjkim    Bit = 1 << ACPI_MOD_32 (OwnerId);
224244971Sjkim
225244971Sjkim    /* Free the owner ID only if it is valid */
226244971Sjkim
227244971Sjkim    if (AcpiGbl_OwnerIdMask[Index] & Bit)
228244971Sjkim    {
229244971Sjkim        AcpiGbl_OwnerIdMask[Index] ^= Bit;
230244971Sjkim    }
231244971Sjkim    else
232244971Sjkim    {
233244971Sjkim        ACPI_ERROR ((AE_INFO,
234244971Sjkim            "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
235244971Sjkim    }
236244971Sjkim
237244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
238244971Sjkim    return_VOID;
239244971Sjkim}
240