diff --git a/drivers/bus/acpi/CMakeLists.txt b/drivers/bus/acpi/CMakeLists.txt index b4d039fda22..0473748a4a3 100644 --- a/drivers/bus/acpi/CMakeLists.txt +++ b/drivers/bus/acpi/CMakeLists.txt @@ -59,6 +59,7 @@ list(APPEND ACPICA_SOURCE acpica/executer/exresnte.c acpica/executer/exresolv.c acpica/executer/exresop.c + acpica/executer/exserial.c acpica/executer/exstore.c acpica/executer/exstoren.c acpica/executer/exstorob.c diff --git a/drivers/bus/acpi/acpica/dispatcher/dsfield.c b/drivers/bus/acpi/acpica/dispatcher/dsfield.c index 60e819f3015..85744cb42ac 100644 --- a/drivers/bus/acpi/acpica/dispatcher/dsfield.c +++ b/drivers/bus/acpi/acpica/dispatcher/dsfield.c @@ -49,6 +49,10 @@ #include "acnamesp.h" #include "acparser.h" +#ifdef ACPI_EXEC_APP +#include "aecommon.h" +#endif + #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME ("dsfield") @@ -322,6 +326,13 @@ AcpiDsGetFieldNames ( UINT64 Position; ACPI_PARSE_OBJECT *Child; +#ifdef ACPI_EXEC_APP + UINT64 Value = 0; + ACPI_OPERAND_OBJECT *ResultDesc; + ACPI_OPERAND_OBJECT *ObjDesc; + char *NamePath; +#endif + ACPI_FUNCTION_TRACE_PTR (DsGetFieldNames, Info); @@ -456,6 +467,18 @@ AcpiDsGetFieldNames ( { return_ACPI_STATUS (Status); } +#ifdef ACPI_EXEC_APP + NamePath = AcpiNsGetExternalPathname (Info->FieldNode); + ObjDesc = AcpiUtCreateIntegerObject (Value); + if (ACPI_SUCCESS (AeLookupInitFileEntry (NamePath, &Value))) + { + AcpiExWriteDataToField (ObjDesc, + AcpiNsGetAttachedObject (Info->FieldNode), + &ResultDesc); + } + AcpiUtRemoveReference (ObjDesc); + ACPI_FREE (NamePath); +#endif } } @@ -648,6 +671,9 @@ AcpiDsInitFieldObjects ( Flags |= ACPI_NS_TEMPORARY; } +#ifdef ACPI_EXEC_APP + Flags |= ACPI_NS_OVERRIDE_IF_FOUND; +#endif /* * Walk the list of entries in the FieldList * Note: FieldList can be of zero length. In this case, Arg will be NULL. diff --git a/drivers/bus/acpi/acpica/events/evregion.c b/drivers/bus/acpi/acpica/events/evregion.c index 390de5a20f4..9cee4923644 100644 --- a/drivers/bus/acpi/acpica/events/evregion.c +++ b/drivers/bus/acpi/acpica/events/evregion.c @@ -730,6 +730,20 @@ AcpiEvExecuteRegMethods ( ACPI_FUNCTION_TRACE (EvExecuteRegMethods); + /* + * These address spaces do not need a call to _REG, since the ACPI + * specification defines them as: "must always be accessible". Since + * they never change state (never become unavailable), no need to ever + * call _REG on them. Also, a DataTable is not a "real" address space, + * so do not call _REG. September 2018. + */ + if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) || + (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) || + (SpaceId == ACPI_ADR_SPACE_DATA_TABLE)) + { + return_VOID; + } + Info.SpaceId = SpaceId; Info.Function = Function; Info.RegRunCount = 0; @@ -796,8 +810,8 @@ AcpiEvRegRun ( } /* - * We only care about regions.and objects that are allowed to have address - * space handlers + * We only care about regions and objects that are allowed to have + * address space handlers */ if ((Node->Type != ACPI_TYPE_REGION) && (Node != AcpiGbl_RootNode)) diff --git a/drivers/bus/acpi/acpica/events/evrgnini.c b/drivers/bus/acpi/acpica/events/evrgnini.c index 0ab23c1094f..a8b576c79af 100644 --- a/drivers/bus/acpi/acpica/events/evrgnini.c +++ b/drivers/bus/acpi/acpica/events/evrgnini.c @@ -50,12 +50,6 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evrgnini") -/* Local prototypes */ - -static BOOLEAN -AcpiEvIsPciRootBridge ( - ACPI_NAMESPACE_NODE *Node); - /******************************************************************************* * @@ -382,7 +376,7 @@ AcpiEvPciConfigRegionSetup ( * ******************************************************************************/ -static BOOLEAN +BOOLEAN AcpiEvIsPciRootBridge ( ACPI_NAMESPACE_NODE *Node) { diff --git a/drivers/bus/acpi/acpica/events/evxfregn.c b/drivers/bus/acpi/acpica/events/evxfregn.c index 99d5edb999e..45bd7d6ee2f 100644 --- a/drivers/bus/acpi/acpica/events/evxfregn.c +++ b/drivers/bus/acpi/acpica/events/evxfregn.c @@ -246,7 +246,6 @@ AcpiRemoveAddressSpaceHandler ( * DetachRegion removed the previous head. */ RegionObj = HandlerObj->AddressSpace.RegionList; - } /* Remove this Handler object from the list */ diff --git a/drivers/bus/acpi/acpica/executer/exfield.c b/drivers/bus/acpi/acpica/executer/exfield.c index 3b7fc93c39c..fb6138a88f2 100644 --- a/drivers/bus/acpi/acpica/executer/exfield.c +++ b/drivers/bus/acpi/acpica/executer/exfield.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: exfield - ACPI AML (p-code) execution - field manipulation + * Module Name: exfield - AML execution - FieldUnit read/write * *****************************************************************************/ @@ -51,72 +51,68 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exfield") -/* Local prototypes */ -static UINT32 -AcpiExGetSerialAccessLength ( - UINT32 AccessorType, - UINT32 AccessLength); +/* + * This table maps the various Attrib protocols to the byte transfer + * length. Used for the generic serial bus. + */ +#define ACPI_INVALID_PROTOCOL_ID 0x80 +#define ACPI_MAX_PROTOCOL_ID 0x0F + +const UINT8 AcpiProtocolLengths[] = +{ + ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */ + ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */ + 0x00, /* 2 - ATTRIB_QUICK */ + ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */ + 0x01, /* 4 - ATTRIB_SEND_RECEIVE */ + ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */ + 0x01, /* 6 - ATTRIB_BYTE */ + ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */ + 0x02, /* 8 - ATTRIB_WORD */ + ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */ + 0xFF, /* A - ATTRIB_BLOCK */ + 0xFF, /* B - ATTRIB_BYTES */ + 0x02, /* C - ATTRIB_PROCESS_CALL */ + 0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */ + 0xFF, /* E - ATTRIB_RAW_BYTES */ + 0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */ +}; /******************************************************************************* * - * FUNCTION: AcpiExGetSerialAccessLength + * FUNCTION: AcpiExGetProtocolBufferLength * - * PARAMETERS: AccessorType - The type of the protocol indicated by region + * PARAMETERS: ProtocolId - The type of the protocol indicated by region * field access attributes - * AccessLength - The access length of the region field + * ReturnLength - Where the protocol byte transfer length is + * returned * - * RETURN: Decoded access length + * RETURN: Status and decoded byte transfer length * * DESCRIPTION: This routine returns the length of the GenericSerialBus * protocol bytes * ******************************************************************************/ -static UINT32 -AcpiExGetSerialAccessLength ( - UINT32 AccessorType, - UINT32 AccessLength) +ACPI_STATUS +AcpiExGetProtocolBufferLength ( + UINT32 ProtocolId, + UINT32 *ReturnLength) { - UINT32 Length; - - switch (AccessorType) + if ((ProtocolId > ACPI_MAX_PROTOCOL_ID) || + (AcpiProtocolLengths[ProtocolId] == ACPI_INVALID_PROTOCOL_ID)) { - case AML_FIELD_ATTRIB_QUICK: + ACPI_ERROR ((AE_INFO, + "Invalid Field/AccessAs protocol ID: 0x%4.4X", ProtocolId)); - Length = 0; - break; - - case AML_FIELD_ATTRIB_SEND_RCV: - case AML_FIELD_ATTRIB_BYTE: - - Length = 1; - break; - - case AML_FIELD_ATTRIB_WORD: - case AML_FIELD_ATTRIB_WORD_CALL: - - Length = 2; - break; - - case AML_FIELD_ATTRIB_MULTIBYTE: - case AML_FIELD_ATTRIB_RAW_BYTES: - case AML_FIELD_ATTRIB_RAW_PROCESS: - - Length = AccessLength; - break; - - case AML_FIELD_ATTRIB_BLOCK: - case AML_FIELD_ATTRIB_BLOCK_CALL: - default: - - Length = ACPI_GSBUS_BUFFER_SIZE - 2; - break; + return (AE_AML_PROTOCOL); } - return (Length); + *ReturnLength = AcpiProtocolLengths[ProtocolId]; + return (AE_OK); } @@ -143,10 +139,8 @@ AcpiExReadDataFromField ( { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *BufferDesc; - ACPI_SIZE Length; void *Buffer; - UINT32 Function; - UINT16 AccessorType; + UINT32 BufferLength; ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); @@ -179,63 +173,14 @@ AcpiExReadDataFromField ( } } else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && - (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || - ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || - ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) { - /* - * This is an SMBus, GSBus or IPMI read. We must create a buffer to - * hold the data and then directly access the region handler. - * - * Note: SMBus and GSBus protocol value is passed in upper 16-bits - * of Function - */ - if (ObjDesc->Field.RegionObj->Region.SpaceId == - ACPI_ADR_SPACE_SMBUS) - { - Length = ACPI_SMBUS_BUFFER_SIZE; - Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); - } - else if (ObjDesc->Field.RegionObj->Region.SpaceId == - ACPI_ADR_SPACE_GSBUS) - { - AccessorType = ObjDesc->Field.Attribute; - Length = AcpiExGetSerialAccessLength ( - AccessorType, ObjDesc->Field.AccessLength); + /* SMBus, GSBus, IPMI serial */ - /* - * Add additional 2 bytes for the GenericSerialBus data buffer: - * - * Status; (Byte 0 of the data buffer) - * Length; (Byte 1 of the data buffer) - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) - */ - Length += 2; - Function = ACPI_READ | (AccessorType << 16); - } - else /* IPMI */ - { - Length = ACPI_IPMI_BUFFER_SIZE; - Function = ACPI_READ; - } - - BufferDesc = AcpiUtCreateBufferObject (Length); - if (!BufferDesc) - { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Lock entire transaction if requested */ - - AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); - - /* Call the region handler for the read */ - - Status = AcpiExAccessRegion (ObjDesc, 0, - ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); - - AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); - goto Exit; + Status = AcpiExReadSerialBus (ObjDesc, RetBufferDesc); + return_ACPI_STATUS (Status); } /* @@ -248,14 +193,14 @@ AcpiExReadDataFromField ( * * Note: Field.length is in bits. */ - Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( + BufferLength = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( ObjDesc->Field.BitLength); - if (Length > AcpiGbl_IntegerByteWidth) + if (BufferLength > AcpiGbl_IntegerByteWidth) { /* Field is too large for an Integer, create a Buffer instead */ - BufferDesc = AcpiUtCreateBufferObject (Length); + BufferDesc = AcpiUtCreateBufferObject (BufferLength); if (!BufferDesc) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -272,47 +217,22 @@ AcpiExReadDataFromField ( return_ACPI_STATUS (AE_NO_MEMORY); } - Length = AcpiGbl_IntegerByteWidth; + BufferLength = AcpiGbl_IntegerByteWidth; Buffer = &BufferDesc->Integer.Value; } if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) { - /* - * For GPIO (GeneralPurposeIo), the Address will be the bit offset - * from the previous Connection() operator, making it effectively a - * pin number index. The BitLength is the length of the field, which - * is thus the number of pins. - */ - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "GPIO FieldRead [FROM]: Pin %u Bits %u\n", - ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); + /* General Purpose I/O */ - /* Lock entire transaction if requested */ - - AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); - - /* Perform the write */ - - Status = AcpiExAccessRegion ( - ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); - - AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); - if (ACPI_FAILURE (Status)) - { - AcpiUtRemoveReference (BufferDesc); - } - else - { - *RetBufferDesc = BufferDesc; - } - return_ACPI_STATUS (Status); + Status = AcpiExReadGpio (ObjDesc, Buffer); + goto Exit; } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", - ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); + ObjDesc, ObjDesc->Common.Type, Buffer, BufferLength)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", ObjDesc->CommonField.BitLength, @@ -325,7 +245,7 @@ AcpiExReadDataFromField ( /* Read from the field */ - Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); + Status = AcpiExExtractFromField (ObjDesc, Buffer, BufferLength); AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); @@ -364,11 +284,8 @@ AcpiExWriteDataToField ( ACPI_OPERAND_OBJECT **ResultDesc) { ACPI_STATUS Status; - UINT32 Length; + UINT32 BufferLength; void *Buffer; - ACPI_OPERAND_OBJECT *BufferDesc; - UINT32 Function; - UINT16 AccessorType; ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); @@ -397,131 +314,21 @@ AcpiExWriteDataToField ( } } else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && - (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || - ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || - ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) { - /* - * This is an SMBus, GSBus or IPMI write. We will bypass the entire - * field mechanism and handoff the buffer directly to the handler. - * For these address spaces, the buffer is bi-directional; on a - * write, return data is returned in the same buffer. - * - * Source must be a buffer of sufficient size: - * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or - * ACPI_IPMI_BUFFER_SIZE. - * - * Note: SMBus and GSBus protocol type is passed in upper 16-bits - * of Function - */ - if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) - { - ACPI_ERROR ((AE_INFO, - "SMBus/IPMI/GenericSerialBus write requires " - "Buffer, found type %s", - AcpiUtGetObjectTypeName (SourceDesc))); + /* General Purpose I/O */ - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - } - - if (ObjDesc->Field.RegionObj->Region.SpaceId == - ACPI_ADR_SPACE_SMBUS) - { - Length = ACPI_SMBUS_BUFFER_SIZE; - Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); - } - else if (ObjDesc->Field.RegionObj->Region.SpaceId == - ACPI_ADR_SPACE_GSBUS) - { - AccessorType = ObjDesc->Field.Attribute; - Length = AcpiExGetSerialAccessLength ( - AccessorType, ObjDesc->Field.AccessLength); - - /* - * Add additional 2 bytes for the GenericSerialBus data buffer: - * - * Status; (Byte 0 of the data buffer) - * Length; (Byte 1 of the data buffer) - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) - */ - Length += 2; - Function = ACPI_WRITE | (AccessorType << 16); - } - else /* IPMI */ - { - Length = ACPI_IPMI_BUFFER_SIZE; - Function = ACPI_WRITE; - } - - if (SourceDesc->Buffer.Length < Length) - { - ACPI_ERROR ((AE_INFO, - "SMBus/IPMI/GenericSerialBus write requires " - "Buffer of length %u, found length %u", - Length, SourceDesc->Buffer.Length)); - - return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); - } - - /* Create the bi-directional buffer */ - - BufferDesc = AcpiUtCreateBufferObject (Length); - if (!BufferDesc) - { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - Buffer = BufferDesc->Buffer.Pointer; - memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); - - /* Lock entire transaction if requested */ - - AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); - - /* - * Perform the write (returns status and perhaps data in the - * same buffer) - */ - Status = AcpiExAccessRegion ( - ObjDesc, 0, (UINT64 *) Buffer, Function); - AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); - - *ResultDesc = BufferDesc; + Status = AcpiExWriteGpio (SourceDesc, ObjDesc, ResultDesc); return_ACPI_STATUS (Status); } else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && - (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) { - /* - * For GPIO (GeneralPurposeIo), we will bypass the entire field - * mechanism and handoff the bit address and bit width directly to - * the handler. The Address will be the bit offset - * from the previous Connection() operator, making it effectively a - * pin number index. The BitLength is the length of the field, which - * is thus the number of pins. - */ - if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) - { - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - } + /* SMBus, GSBus, IPMI serial */ - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", - AcpiUtGetTypeName (SourceDesc->Common.Type), - SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, - ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); - - Buffer = &SourceDesc->Integer.Value; - - /* Lock entire transaction if requested */ - - AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); - - /* Perform the write */ - - Status = AcpiExAccessRegion ( - ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); - AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + Status = AcpiExWriteSerialBus (SourceDesc, ObjDesc, ResultDesc); return_ACPI_STATUS (Status); } @@ -532,30 +339,29 @@ AcpiExWriteDataToField ( case ACPI_TYPE_INTEGER: Buffer = &SourceDesc->Integer.Value; - Length = sizeof (SourceDesc->Integer.Value); + BufferLength = sizeof (SourceDesc->Integer.Value); break; case ACPI_TYPE_BUFFER: Buffer = SourceDesc->Buffer.Pointer; - Length = SourceDesc->Buffer.Length; + BufferLength = SourceDesc->Buffer.Length; break; case ACPI_TYPE_STRING: Buffer = SourceDesc->String.Pointer; - Length = SourceDesc->String.Length; + BufferLength = SourceDesc->String.Length; break; default: - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), - SourceDesc->Common.Type, Buffer, Length)); + SourceDesc->Common.Type, Buffer, BufferLength)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", @@ -571,8 +377,7 @@ AcpiExWriteDataToField ( /* Write to the field */ - Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); + Status = AcpiExInsertIntoField (ObjDesc, Buffer, BufferLength); AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); - return_ACPI_STATUS (Status); } diff --git a/drivers/bus/acpi/acpica/executer/exserial.c b/drivers/bus/acpi/acpica/executer/exserial.c new file mode 100644 index 00000000000..023e48b9680 --- /dev/null +++ b/drivers/bus/acpi/acpica/executer/exserial.c @@ -0,0 +1,416 @@ +/****************************************************************************** + * + * Module Name: exserial - FieldUnit support for serial address spaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2018, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exserial") + + +/******************************************************************************* + * + * FUNCTION: AcpiExReadGpio + * + * PARAMETERS: ObjDesc - The named field to read + * Buffer - Where the return data is returnd + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a Generic Serial Bus + * field + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadGpio ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExReadGpio, ObjDesc); + + + /* + * For GPIO (GeneralPurposeIo), the Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The BitLength is the length of the field, which + * is thus the number of pins. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "GPIO FieldRead [FROM]: Pin %u Bits %u\n", + ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Perform the read */ + + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); + + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteGpio + * + * PARAMETERS: SourceDesc - Contains data to write. Expect to be + * an Integer object. + * ObjDesc - The named field + * ResultDesc - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a General Purpose I/O + * field. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteGpio ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + void *Buffer; + + + ACPI_FUNCTION_TRACE_PTR (ExWriteGpio, ObjDesc); + + + /* + * For GPIO (GeneralPurposeIo), we will bypass the entire field + * mechanism and handoff the bit address and bit width directly to + * the handler. The Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The BitLength is the length of the field, which + * is thus the number of pins. + */ + if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n", + AcpiUtGetTypeName (SourceDesc->Common.Type), + SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, + ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); + + Buffer = &SourceDesc->Integer.Value; + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Perform the write */ + + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReadSerialBus + * + * PARAMETERS: ObjDesc - The named field to read + * ReturnBuffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a serial bus + * (SMBus, IPMI, or GSBus). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadSerialBus ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + UINT32 BufferLength; + ACPI_OPERAND_OBJECT *BufferDesc; + UINT32 Function; + UINT16 AccessorType; + + + ACPI_FUNCTION_TRACE_PTR (ExReadSerialBus, ObjDesc); + + + /* + * This is an SMBus, GSBus or IPMI read. We must create a buffer to + * hold the data and then directly access the region handler. + * + * Note: SMBus and GSBus protocol value is passed in upper 16-bits + * of Function + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + switch (ObjDesc->Field.RegionObj->Region.SpaceId) + { + case ACPI_ADR_SPACE_SMBUS: + + BufferLength = ACPI_SMBUS_BUFFER_SIZE; + Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + BufferLength = ACPI_IPMI_BUFFER_SIZE; + Function = ACPI_READ; + break; + + case ACPI_ADR_SPACE_GSBUS: + + AccessorType = ObjDesc->Field.Attribute; + if (AccessorType == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) + { + ACPI_ERROR ((AE_INFO, + "Invalid direct read using bidirectional write-then-read protocol")); + + return_ACPI_STATUS (AE_AML_PROTOCOL); + } + + Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType)); + + return_ACPI_STATUS (Status); + } + + /* Add header length to get the full size of the buffer */ + + BufferLength += ACPI_SERIAL_HEADER_SIZE; + Function = ACPI_READ | (AccessorType << 16); + break; + + default: + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); + } + + /* Create the local transfer buffer that is returned to the caller */ + + BufferDesc = AcpiUtCreateBufferObject (BufferLength); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Call the region handler for the write-then-read */ + + Status = AcpiExAccessRegion (ObjDesc, 0, + ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + *ReturnBuffer = BufferDesc; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteSerialBus + * + * PARAMETERS: SourceDesc - Contains data to write + * ObjDesc - The named field + * ReturnBuffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a serial bus + * (SMBus, IPMI, GSBus). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteSerialBus ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + UINT32 BufferLength; + UINT32 DataLength; + void *Buffer; + ACPI_OPERAND_OBJECT *BufferDesc; + UINT32 Function; + UINT16 AccessorType; + + + ACPI_FUNCTION_TRACE_PTR (ExWriteSerialBus, ObjDesc); + + + /* + * This is an SMBus, GSBus or IPMI write. We will bypass the entire + * field mechanism and handoff the buffer directly to the handler. + * For these address spaces, the buffer is bidirectional; on a + * write, return data is returned in the same buffer. + * + * Source must be a buffer of sufficient size, these are fixed size: + * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. + * + * Note: SMBus and GSBus protocol type is passed in upper 16-bits + * of Function + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) + { + ACPI_ERROR ((AE_INFO, + "SMBus/IPMI/GenericSerialBus write requires " + "Buffer, found type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + switch (ObjDesc->Field.RegionObj->Region.SpaceId) + { + case ACPI_ADR_SPACE_SMBUS: + + BufferLength = ACPI_SMBUS_BUFFER_SIZE; + DataLength = ACPI_SMBUS_DATA_SIZE; + Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + BufferLength = ACPI_IPMI_BUFFER_SIZE; + DataLength = ACPI_IPMI_DATA_SIZE; + Function = ACPI_WRITE; + break; + + case ACPI_ADR_SPACE_GSBUS: + + AccessorType = ObjDesc->Field.Attribute; + Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType)); + + return_ACPI_STATUS (Status); + } + + /* Add header length to get the full size of the buffer */ + + BufferLength += ACPI_SERIAL_HEADER_SIZE; + DataLength = SourceDesc->Buffer.Pointer[1]; + Function = ACPI_WRITE | (AccessorType << 16); + break; + + default: + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); + } + +#if 0 +OBSOLETE? + /* Check for possible buffer overflow */ + + if (DataLength > SourceDesc->Buffer.Length) + { + ACPI_ERROR ((AE_INFO, + "Length in buffer header (%u)(%u) is greater than " + "the physical buffer length (%u) and will overflow", + DataLength, BufferLength, SourceDesc->Buffer.Length)); + + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } +#endif + + /* Create the transfer/bidirectional/return buffer */ + + BufferDesc = AcpiUtCreateBufferObject (BufferLength); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the input buffer data to the transfer buffer */ + + Buffer = BufferDesc->Buffer.Pointer; + memcpy (Buffer, SourceDesc->Buffer.Pointer, DataLength); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* + * Perform the write (returns status and perhaps data in the + * same buffer) + */ + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) Buffer, Function); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + *ReturnBuffer = BufferDesc; + return_ACPI_STATUS (Status); +} diff --git a/drivers/bus/acpi/acpica/hardware/hwregs.c b/drivers/bus/acpi/acpica/hardware/hwregs.c index cde1458813d..33171f26bba 100644 --- a/drivers/bus/acpi/acpica/hardware/hwregs.c +++ b/drivers/bus/acpi/acpica/hardware/hwregs.c @@ -616,13 +616,20 @@ AcpiHwRegisterRead ( case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock); - Value = (UINT32) Value64; + if (ACPI_SUCCESS (Status)) + { + Value = (UINT32) Value64; + } break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock); - Value = (UINT32) Value64; + if (ACPI_SUCCESS (Status)) + { + Value = (UINT32) Value64; + } + break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ diff --git a/drivers/bus/acpi/acpica/hardware/hwsleep.c b/drivers/bus/acpi/acpica/hardware/hwsleep.c index 8fce247a5f1..02a420f1783 100644 --- a/drivers/bus/acpi/acpica/hardware/hwsleep.c +++ b/drivers/bus/acpi/acpica/hardware/hwsleep.c @@ -90,17 +90,22 @@ AcpiHwLegacySleep ( return_ACPI_STATUS (Status); } - /* - * 1) Disable all GPEs - * 2) Enable all wakeup GPEs - */ + /* Disable all GPEs */ + Status = AcpiHwDisableAllGpes (); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } + Status = AcpiHwClearAcpiStatus(); + if (ACPI_FAILURE(Status)) + { + return_ACPI_STATUS(Status); + } AcpiGbl_SystemAwakeAndRunning = FALSE; + /* Enable all wakeup GPEs */ + Status = AcpiHwEnableAllWakeupGpes (); if (ACPI_FAILURE (Status)) { diff --git a/drivers/bus/acpi/acpica/hardware/hwxfsleep.c b/drivers/bus/acpi/acpica/hardware/hwxfsleep.c index f6e3ec13d5b..f6449565f0a 100644 --- a/drivers/bus/acpi/acpica/hardware/hwxfsleep.c +++ b/drivers/bus/acpi/acpica/hardware/hwxfsleep.c @@ -76,17 +76,17 @@ AcpiHwSleepDispatch ( static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] = { - {ACPI_STRUCT_INIT (legacy_function, + {ACPI_STRUCT_INIT (LegacyFunction, ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep)), - ACPI_STRUCT_INIT (extended_function, + ACPI_STRUCT_INIT (ExtendedFunction, AcpiHwExtendedSleep) }, - {ACPI_STRUCT_INIT (legacy_function, + {ACPI_STRUCT_INIT (LegacyFunction, ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep)), - ACPI_STRUCT_INIT (extended_function, + ACPI_STRUCT_INIT (ExtendedFunction, AcpiHwExtendedWakePrep) }, - {ACPI_STRUCT_INIT (legacy_function, + {ACPI_STRUCT_INIT (Legacy_function, ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake)), - ACPI_STRUCT_INIT (extended_function, + ACPI_STRUCT_INIT (ExtendedFunction, AcpiHwExtendedWake) } }; diff --git a/drivers/bus/acpi/acpica/include/acconfig.h b/drivers/bus/acpi/acpica/include/acconfig.h index 335179ff016..6f9c8d6d504 100644 --- a/drivers/bus/acpi/acpica/include/acconfig.h +++ b/drivers/bus/acpi/acpica/include/acconfig.h @@ -125,7 +125,7 @@ /* Maximum object reference count (detects object deletion issues) */ -#define ACPI_MAX_REFERENCE_COUNT 0x800 +#define ACPI_MAX_REFERENCE_COUNT 0x4000 /* Default page size for use in mapping memory for operation regions */ @@ -210,11 +210,21 @@ #define ACPI_RSDP_CHECKSUM_LENGTH 20 #define ACPI_RSDP_XCHECKSUM_LENGTH 36 -/* SMBus, GSBus and IPMI bidirectional buffer size */ +/* + * SMBus, GSBus and IPMI buffer sizes. All have a 2-byte header, + * containing both Status and Length. + */ +#define ACPI_SERIAL_HEADER_SIZE 2 /* Common for below. Status and Length fields */ + +#define ACPI_SMBUS_DATA_SIZE 32 +#define ACPI_SMBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_SMBUS_DATA_SIZE + +#define ACPI_IPMI_DATA_SIZE 64 +#define ACPI_IPMI_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_IPMI_DATA_SIZE + +#define ACPI_MAX_GSBUS_DATA_SIZE 255 +#define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE -#define ACPI_SMBUS_BUFFER_SIZE 34 -#define ACPI_GSBUS_BUFFER_SIZE 34 -#define ACPI_IPMI_BUFFER_SIZE 66 /* _SxD and _SxW control methods */ diff --git a/drivers/bus/acpi/acpica/include/acdisasm.h b/drivers/bus/acpi/acpica/include/acdisasm.h index e9b7a4876bc..abe3bdf91c2 100644 --- a/drivers/bus/acpi/acpica/include/acdisasm.h +++ b/drivers/bus/acpi/acpica/include/acdisasm.h @@ -472,7 +472,7 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoGeneric[][2]; * dmtable and ahtable */ extern const ACPI_DMTABLE_DATA AcpiDmTableData[]; -extern const AH_TABLE Gbl_AcpiSupportedTables[]; +extern const AH_TABLE AcpiGbl_SupportedTables[]; UINT8 AcpiDmGenerateChecksum ( diff --git a/drivers/bus/acpi/acpica/include/acevents.h b/drivers/bus/acpi/acpica/include/acevents.h index 5559544ec78..d6db0caca54 100644 --- a/drivers/bus/acpi/acpica/include/acevents.h +++ b/drivers/bus/acpi/acpica/include/acevents.h @@ -359,6 +359,10 @@ ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj); +BOOLEAN +AcpiEvIsPciRootBridge ( + ACPI_NAMESPACE_NODE *Node); + /* * evsci - SCI (System Control Interrupt) handling/dispatch diff --git a/drivers/bus/acpi/acpica/include/acexcep.h b/drivers/bus/acpi/acpica/include/acexcep.h index 29c5a77df11..2a5511a7c0a 100644 --- a/drivers/bus/acpi/acpica/include/acexcep.h +++ b/drivers/bus/acpi/acpica/include/acexcep.h @@ -96,6 +96,13 @@ typedef struct acpi_exception_info #define AE_OK (ACPI_STATUS) 0x0000 +#define ACPI_ENV_EXCEPTION(Status) (Status & AE_CODE_ENVIRONMENTAL) +#define ACPI_AML_EXCEPTION(Status) (Status & AE_CODE_AML) +#define ACPI_PROG_EXCEPTION(Status) (Status & AE_CODE_PROGRAMMER) +#define ACPI_TABLE_EXCEPTION(Status) (Status & AE_CODE_ACPI_TABLES) +#define ACPI_CNTL_EXCEPTION(Status) (Status & AE_CODE_CONTROL) + + /* * Environmental exceptions */ @@ -205,8 +212,10 @@ typedef struct acpi_exception_info #define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021) #define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022) #define AE_AML_TARGET_TYPE EXCEP_AML (0x0023) +#define AE_AML_PROTOCOL EXCEP_AML (0x0024) +#define AE_AML_BUFFER_LENGTH EXCEP_AML (0x0025) -#define AE_CODE_AML_MAX 0x0023 +#define AE_CODE_AML_MAX 0x0025 /* @@ -337,7 +346,9 @@ static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Aml[] = EXCEP_TXT ("AE_AML_ILLEGAL_ADDRESS", "A memory, I/O, or PCI configuration address is invalid"), EXCEP_TXT ("AE_AML_LOOP_TIMEOUT", "An AML While loop exceeded the maximum execution time"), EXCEP_TXT ("AE_AML_UNINITIALIZED_NODE", "A namespace node is uninitialized or unresolved"), - EXCEP_TXT ("AE_AML_TARGET_TYPE", "A target operand of an incorrect type was encountered") + EXCEP_TXT ("AE_AML_TARGET_TYPE", "A target operand of an incorrect type was encountered"), + EXCEP_TXT ("AE_AML_PROTOCOL", "Violation of a fixed ACPI protocol"), + EXCEP_TXT ("AE_AML_BUFFER_LENGTH", "The length of the buffer is invalid/incorrect") }; static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Ctrl[] = diff --git a/drivers/bus/acpi/acpica/include/acinterp.h b/drivers/bus/acpi/acpica/include/acinterp.h index b84467c693f..1e4925f77fb 100644 --- a/drivers/bus/acpi/acpica/include/acinterp.h +++ b/drivers/bus/acpi/acpica/include/acinterp.h @@ -177,6 +177,11 @@ AcpiExTracePoint ( * exfield - ACPI AML (p-code) execution - field manipulation */ ACPI_STATUS +AcpiExGetProtocolBufferLength ( + UINT32 ProtocolId, + UINT32 *ReturnLength); + +ACPI_STATUS AcpiExCommonBufferSetup ( ACPI_OPERAND_OBJECT *ObjDesc, UINT32 BufferLength, @@ -386,6 +391,32 @@ AcpiExPrepFieldValue ( ACPI_CREATE_FIELD_INFO *Info); +/* + * exserial - FieldUnit support for serial address spaces + */ +ACPI_STATUS +AcpiExReadSerialBus ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + +ACPI_STATUS +AcpiExWriteSerialBus ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + +ACPI_STATUS +AcpiExReadGpio ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer); + +ACPI_STATUS +AcpiExWriteGpio ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + + /* * exsystem - Interface to OS services */ diff --git a/drivers/bus/acpi/acpica/include/aclocal.h b/drivers/bus/acpi/acpica/include/aclocal.h index d7ffdadfaad..0a599f14cd7 100644 --- a/drivers/bus/acpi/acpica/include/aclocal.h +++ b/drivers/bus/acpi/acpica/include/aclocal.h @@ -219,8 +219,8 @@ typedef struct acpi_namespace_node #define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */ #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (InstallMethod) */ +#define ANOBJ_NODE_EARLY_INIT 0x80 /* AcpiExec only: Node was create via init file (-fi) */ -#define IMPLICIT_EXTERNAL 0x02 /* iASL only: This object created implicitly via External */ #define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ #define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ #define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ @@ -489,9 +489,9 @@ typedef struct acpi_simple_repair_info typedef struct acpi_reg_walk_info { - ACPI_ADR_SPACE_TYPE SpaceId; UINT32 Function; UINT32 RegRunCount; + ACPI_ADR_SPACE_TYPE SpaceId; } ACPI_REG_WALK_INFO; diff --git a/drivers/bus/acpi/acpica/include/acnamesp.h b/drivers/bus/acpi/acpica/include/acnamesp.h index 51d4d933492..b9a34f2203d 100644 --- a/drivers/bus/acpi/acpica/include/acnamesp.h +++ b/drivers/bus/acpi/acpica/include/acnamesp.h @@ -60,14 +60,15 @@ /* Flags for AcpiNsLookup, AcpiNsSearchAndEnter */ #define ACPI_NS_NO_UPSEARCH 0 -#define ACPI_NS_SEARCH_PARENT 0x01 -#define ACPI_NS_DONT_OPEN_SCOPE 0x02 -#define ACPI_NS_NO_PEER_SEARCH 0x04 -#define ACPI_NS_ERROR_IF_FOUND 0x08 -#define ACPI_NS_PREFIX_IS_SCOPE 0x10 -#define ACPI_NS_EXTERNAL 0x20 -#define ACPI_NS_TEMPORARY 0x40 -#define ACPI_NS_OVERRIDE_IF_FOUND 0x80 +#define ACPI_NS_SEARCH_PARENT 0x0001 +#define ACPI_NS_DONT_OPEN_SCOPE 0x0002 +#define ACPI_NS_NO_PEER_SEARCH 0x0004 +#define ACPI_NS_ERROR_IF_FOUND 0x0008 +#define ACPI_NS_PREFIX_IS_SCOPE 0x0010 +#define ACPI_NS_EXTERNAL 0x0020 +#define ACPI_NS_TEMPORARY 0x0040 +#define ACPI_NS_OVERRIDE_IF_FOUND 0x0080 +#define ACPI_NS_EARLY_INIT 0x0100 /* Flags for AcpiNsWalkNamespace */ diff --git a/drivers/bus/acpi/acpica/include/acpixf.h b/drivers/bus/acpi/acpica/include/acpixf.h index ebf59813568..294308ef464 100644 --- a/drivers/bus/acpi/acpica/include/acpixf.h +++ b/drivers/bus/acpi/acpica/include/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20180531 +#define ACPI_CA_VERSION 0x20181003 #include "acconfig.h" #include "actypes.h" diff --git a/drivers/bus/acpi/acpica/include/acutils.h b/drivers/bus/acpi/acpica/include/acutils.h index 5c3d6717245..dc7750808e3 100644 --- a/drivers/bus/acpi/acpica/include/acutils.h +++ b/drivers/bus/acpi/acpica/include/acutils.h @@ -254,6 +254,10 @@ BOOLEAN AcpiUtDetectHexPrefix ( char **String); +void +AcpiUtRemoveHexPrefix ( + char **String); + BOOLEAN AcpiUtDetectOctalPrefix ( char **String); diff --git a/drivers/bus/acpi/acpica/include/amlcode.h b/drivers/bus/acpi/acpica/include/amlcode.h index 0f7e7ec2d11..216f784ca29 100644 --- a/drivers/bus/acpi/acpica/include/amlcode.h +++ b/drivers/bus/acpi/acpica/include/amlcode.h @@ -486,16 +486,16 @@ typedef enum */ typedef enum { - AML_FIELD_ATTRIB_QUICK = 0x02, - AML_FIELD_ATTRIB_SEND_RCV = 0x04, - AML_FIELD_ATTRIB_BYTE = 0x06, - AML_FIELD_ATTRIB_WORD = 0x08, - AML_FIELD_ATTRIB_BLOCK = 0x0A, - AML_FIELD_ATTRIB_MULTIBYTE = 0x0B, - AML_FIELD_ATTRIB_WORD_CALL = 0x0C, - AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D, - AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, - AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F + AML_FIELD_ATTRIB_QUICK = 0x02, + AML_FIELD_ATTRIB_SEND_RECEIVE = 0x04, + AML_FIELD_ATTRIB_BYTE = 0x06, + AML_FIELD_ATTRIB_WORD = 0x08, + AML_FIELD_ATTRIB_BLOCK = 0x0A, + AML_FIELD_ATTRIB_BYTES = 0x0B, + AML_FIELD_ATTRIB_PROCESS_CALL = 0x0C, + AML_FIELD_ATTRIB_BLOCK_PROCESS_CALL = 0x0D, + AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, + AML_FIELD_ATTRIB_RAW_PROCESS_BYTES = 0x0F } AML_ACCESS_ATTRIBUTE; diff --git a/drivers/bus/acpi/acpica/namespace/nsaccess.c b/drivers/bus/acpi/acpica/namespace/nsaccess.c index 0facc4f10bf..a5047a3e801 100644 --- a/drivers/bus/acpi/acpica/namespace/nsaccess.c +++ b/drivers/bus/acpi/acpica/namespace/nsaccess.c @@ -616,6 +616,15 @@ AcpiNsLookup ( CurrentNode)); } +#ifdef ACPI_EXEC_APP + if ((Status == AE_ALREADY_EXISTS) && + (ThisNode->Flags & ANOBJ_NODE_EARLY_INIT)) + { + ThisNode->Flags &= ~ANOBJ_NODE_EARLY_INIT; + Status = AE_OK; + } +#endif + #ifdef ACPI_ASL_COMPILER /* * If this ACPI name already exists within the namespace as an @@ -673,13 +682,6 @@ AcpiNsLookup ( else { -#ifdef ACPI_ASL_COMPILER - if (!AcpiGbl_DisasmFlag && (ThisNode->Flags & ANOBJ_IS_EXTERNAL)) - { - ThisNode->Flags &= ~IMPLICIT_EXTERNAL; - } -#endif - /* * Sanity typecheck of the target object: * @@ -744,6 +746,13 @@ AcpiNsLookup ( } } +#ifdef ACPI_EXEC_APP + if (Flags & ACPI_NS_EARLY_INIT) + { + ThisNode->Flags |= ANOBJ_NODE_EARLY_INIT; + } +#endif + *ReturnNode = ThisNode; return_ACPI_STATUS (AE_OK); } diff --git a/drivers/bus/acpi/acpica/namespace/nseval.c b/drivers/bus/acpi/acpica/namespace/nseval.c index 8e6b32f4527..6c1eaa76ada 100644 --- a/drivers/bus/acpi/acpica/namespace/nseval.c +++ b/drivers/bus/acpi/acpica/namespace/nseval.c @@ -320,11 +320,11 @@ AcpiNsEvaluate ( Status = AE_OK; } - else if (ACPI_FAILURE(Status)) + else if (ACPI_FAILURE(Status)) { /* If ReturnObject exists, delete it */ - if (Info->ReturnObject) + if (Info->ReturnObject) { AcpiUtRemoveReference (Info->ReturnObject); Info->ReturnObject = NULL; diff --git a/drivers/bus/acpi/acpica/namespace/nssearch.c b/drivers/bus/acpi/acpica/namespace/nssearch.c index 88e5155c561..97ed8edc204 100644 --- a/drivers/bus/acpi/acpica/namespace/nssearch.c +++ b/drivers/bus/acpi/acpica/namespace/nssearch.c @@ -437,7 +437,6 @@ AcpiNsSearchAndEnter ( (WalkState && WalkState->Opcode == AML_SCOPE_OP)) { NewNode->Flags |= ANOBJ_IS_EXTERNAL; - NewNode->Flags |= IMPLICIT_EXTERNAL; } #endif diff --git a/drivers/bus/acpi/acpica/parser/psloop.c b/drivers/bus/acpi/acpica/parser/psloop.c index aeeb2f6393c..727a78b6e40 100644 --- a/drivers/bus/acpi/acpica/parser/psloop.c +++ b/drivers/bus/acpi/acpica/parser/psloop.c @@ -56,6 +56,7 @@ #include "acdispat.h" #include "amlcode.h" #include "acconvert.h" +#include "acnamesp.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("psloop") @@ -537,6 +538,18 @@ AcpiPsParseLoop ( Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); if (ACPI_FAILURE (Status)) { + /* + * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by + * executing it as a control method. However, if we encounter + * an error while loading the table, we need to keep trying to + * load the table rather than aborting the table load. Set the + * status to AE_OK to proceed with the table load. + */ + if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && + Status == AE_ALREADY_EXISTS) + { + Status = AE_OK; + } if (Status == AE_CTRL_PARSE_CONTINUE) { continue; @@ -557,18 +570,20 @@ AcpiPsParseLoop ( { return_ACPI_STATUS (Status); } - if (WalkState->Opcode == AML_SCOPE_OP) + if (AcpiNsOpensScope ( + AcpiPsGetOpcodeInfo (WalkState->Opcode)->ObjectType)) { /* - * If the scope op fails to parse, skip the body of the - * scope op because the parse failure indicates that the - * device may not exist. + * If the scope/device op fails to parse, skip the body of + * the scope op because the parse failure indicates that + * the device may not exist. */ + ACPI_ERROR ((AE_INFO, "Skip parsing opcode %s", + AcpiPsGetOpcodeName (WalkState->Opcode))); WalkState->ParserState.Aml = WalkState->Aml + 1; WalkState->ParserState.Aml = AcpiPsGetNextPackageEnd(&WalkState->ParserState); WalkState->Aml = WalkState->ParserState.Aml; - ACPI_ERROR ((AE_INFO, "Skipping Scope block")); } continue; @@ -726,6 +741,22 @@ AcpiPsParseLoop ( { Status = AE_OK; } + else if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && + (ACPI_AML_EXCEPTION(Status) || Status == AE_ALREADY_EXISTS || + Status == AE_NOT_FOUND)) + { + /* + * ACPI_PARSE_MODULE_LEVEL flag means that we are currently + * loading a table by executing it as a control method. + * However, if we encounter an error while loading the table, + * we need to keep trying to load the table rather than + * aborting the table load (setting the status to AE_OK + * continues the table load). If we get a failure at this + * point, it means that the dispatcher got an error while + * trying to execute the Op. + */ + Status = AE_OK; + } } Status = AcpiPsCompleteOp (WalkState, &Op, Status); diff --git a/drivers/bus/acpi/acpica/tables/tbdata.c b/drivers/bus/acpi/acpica/tables/tbdata.c index a3779b6f244..87fd012ca68 100644 --- a/drivers/bus/acpi/acpica/tables/tbdata.c +++ b/drivers/bus/acpi/acpica/tables/tbdata.c @@ -603,9 +603,9 @@ AcpiTbVerifyTempTable ( { if (Status != AE_CTRL_TERMINATE) { - ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, + ACPI_EXCEPTION ((AE_INFO, Status, "%4.4s 0x%8.8X%8.8X" - " Table is duplicated", + " Table is already loaded", AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? TableDesc->Signature.Ascii : "????", ACPI_FORMAT_UINT64 (TableDesc->Address))); diff --git a/drivers/bus/acpi/acpica/utilities/utdelete.c b/drivers/bus/acpi/acpica/utilities/utdelete.c index 83e5a6302ec..2bace65aa4b 100644 --- a/drivers/bus/acpi/acpica/utilities/utdelete.c +++ b/drivers/bus/acpi/acpica/utilities/utdelete.c @@ -412,6 +412,7 @@ AcpiUtUpdateRefCount ( UINT16 OriginalCount; UINT16 NewCount = 0; ACPI_CPU_FLAGS LockFlags; + char *Message; ACPI_FUNCTION_NAME (UtUpdateRefCount); @@ -452,6 +453,7 @@ AcpiUtUpdateRefCount ( "Obj %p Type %.2X [%s] Refs %.2X [Incremented]\n", Object, Object->Common.Type, AcpiUtGetObjectTypeName (Object), NewCount)); + Message = "Incremement"; break; case REF_DECREMENT: @@ -483,6 +485,7 @@ AcpiUtUpdateRefCount ( { AcpiUtDeleteInternalObj (Object); } + Message = "Decrement"; break; default: @@ -500,8 +503,8 @@ AcpiUtUpdateRefCount ( if (NewCount > ACPI_MAX_REFERENCE_COUNT) { ACPI_WARNING ((AE_INFO, - "Large Reference Count (0x%X) in object %p, Type=0x%.2X", - NewCount, Object, Object->Common.Type)); + "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s", + NewCount, Object, Object->Common.Type, Message)); } } diff --git a/drivers/bus/acpi/acpica/utilities/uterror.c b/drivers/bus/acpi/acpica/utilities/uterror.c index abc7056acd0..1956ff3cc89 100644 --- a/drivers/bus/acpi/acpica/utilities/uterror.c +++ b/drivers/bus/acpi/acpica/utilities/uterror.c @@ -244,19 +244,19 @@ AcpiUtPrefixedNamespaceError ( { case AE_ALREADY_EXISTS: - AcpiOsPrintf ("\n" ACPI_MSG_BIOS_ERROR); + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); Message = "Failure creating"; break; case AE_NOT_FOUND: - AcpiOsPrintf ("\n" ACPI_MSG_BIOS_ERROR); + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); Message = "Could not resolve"; break; default: - AcpiOsPrintf ("\n" ACPI_MSG_ERROR); + AcpiOsPrintf (ACPI_MSG_ERROR); Message = "Failure resolving"; break; } diff --git a/drivers/bus/acpi/acpica/utilities/utstrsuppt.c b/drivers/bus/acpi/acpica/utilities/utstrsuppt.c index ca6a31ffbbe..22020f7e9f9 100644 --- a/drivers/bus/acpi/acpica/utilities/utstrsuppt.c +++ b/drivers/bus/acpi/acpica/utilities/utstrsuppt.c @@ -311,15 +311,39 @@ BOOLEAN AcpiUtDetectHexPrefix ( char **String) { + char *InitialPosition = *String; + AcpiUtRemoveHexPrefix (String); + if (*String != InitialPosition) + { + return (TRUE); /* String is past leading 0x */ + } + + return (FALSE); /* Not a hex string */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveHexPrefix + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: none + * + * DESCRIPTION: Remove a hex "0x" prefix + * + ******************************************************************************/ + +void +AcpiUtRemoveHexPrefix ( + char **String) +{ if ((**String == ACPI_ASCII_ZERO) && (tolower ((int) *(*String + 1)) == 'x')) { *String += 2; /* Go past the leading 0x */ - return (TRUE); } - - return (FALSE); /* Not a hex string */ } diff --git a/drivers/bus/acpi/acpica/utilities/utstrtoul64.c b/drivers/bus/acpi/acpica/utilities/utstrtoul64.c index 6c6a1b76dc6..146b6587cde 100644 --- a/drivers/bus/acpi/acpica/utilities/utstrtoul64.c +++ b/drivers/bus/acpi/acpica/utilities/utstrtoul64.c @@ -275,7 +275,7 @@ AcpiUtImplicitStrtoul64 ( * implicit conversions, and the "0x" prefix is "not allowed". * However, allow a "0x" prefix as an ACPI extension. */ - AcpiUtDetectHexPrefix (&String); + AcpiUtRemoveHexPrefix (&String); if (!AcpiUtRemoveLeadingZeros (&String)) {