2009-11-12 04:44:06 +03:00
/******************************************************************************
*
* Module Name : nsrepair2 - Repair for objects returned by specific
* predefined methods
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2013-01-25 09:38:56 +04:00
* Copyright ( C ) 2000 - 2013 , Intel Corp .
2009-11-12 04:44:06 +03:00
* 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/acpi.h>
# include "accommon.h"
# include "acnamesp.h"
# define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME ( " nsrepair2 " )
/*
* Information structure and handler for ACPI predefined names that can
* be repaired on a per - name basis .
*/
typedef
2013-05-30 06:00:01 +04:00
acpi_status ( * acpi_repair_function ) ( struct acpi_evaluate_info * info ,
2012-12-19 09:37:15 +04:00
union acpi_operand_object
* * return_object_ptr ) ;
2009-11-12 04:44:06 +03:00
typedef struct acpi_repair_info {
char name [ ACPI_NAME_SIZE ] ;
acpi_repair_function repair_function ;
} acpi_repair_info ;
/* Local prototypes */
2013-03-08 13:23:03 +04:00
static const struct acpi_repair_info * acpi_ns_match_complex_repair ( struct
acpi_namespace_node
* node ) ;
2009-11-12 04:44:06 +03:00
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_ALR ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr ) ;
2010-09-15 10:11:02 +04:00
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_CID ( struct acpi_evaluate_info * info ,
2010-09-15 10:11:02 +04:00
union acpi_operand_object * * return_object_ptr ) ;
2009-12-11 09:53:11 +03:00
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_FDE ( struct acpi_evaluate_info * info ,
2009-12-11 09:53:11 +03:00
union acpi_operand_object * * return_object_ptr ) ;
2010-09-15 10:11:02 +04:00
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_HID ( struct acpi_evaluate_info * info ,
2010-09-15 10:11:02 +04:00
union acpi_operand_object * * return_object_ptr ) ;
2009-11-12 04:44:06 +03:00
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_PSS ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr ) ;
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_TSS ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr ) ;
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_check_sorted_list ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * return_object ,
u32 expected_count ,
u32 sort_index ,
u8 sort_direction , char * sort_key_name ) ;
2010-01-21 04:08:31 +03:00
static void
2009-11-12 04:44:06 +03:00
acpi_ns_sort_list ( union acpi_operand_object * * elements ,
u32 count , u32 index , u8 sort_direction ) ;
/* Values for sort_direction above */
# define ACPI_SORT_ASCENDING 0
# define ACPI_SORT_DESCENDING 1
/*
* This table contains the names of the predefined methods for which we can
* perform more complex repairs .
*
2009-12-11 09:53:11 +03:00
* As necessary :
*
* _ALR : Sort the list ascending by ambient_illuminance
2010-09-15 10:11:02 +04:00
* _CID : Strings : uppercase all , remove any leading asterisk
2009-12-11 10:24:27 +03:00
* _FDE : Convert Buffer of BYTEs to a Buffer of DWORDs
* _GTM : Convert Buffer of BYTEs to a Buffer of DWORDs
2010-09-15 10:11:02 +04:00
* _HID : Strings : uppercase all , remove any leading asterisk
2009-12-11 09:53:11 +03:00
* _PSS : Sort the list descending by Power
* _TSS : Sort the list descending by Power
2010-05-26 07:03:56 +04:00
*
* Names that must be packages , but cannot be sorted :
*
* _BCL : Values are tied to the Package index where they appear , and cannot
* be moved or sorted . These index values are used for _BQC and _BCM .
* However , we can fix the case where a buffer is returned , by converting
* it to a Package of integers .
2009-11-12 04:44:06 +03:00
*/
static const struct acpi_repair_info acpi_ns_repairable_names [ ] = {
{ " _ALR " , acpi_ns_repair_ALR } ,
2010-09-15 10:11:02 +04:00
{ " _CID " , acpi_ns_repair_CID } ,
2009-12-11 09:53:11 +03:00
{ " _FDE " , acpi_ns_repair_FDE } ,
{ " _GTM " , acpi_ns_repair_FDE } , /* _GTM has same repair as _FDE */
2010-09-15 10:11:02 +04:00
{ " _HID " , acpi_ns_repair_HID } ,
2009-11-12 04:44:06 +03:00
{ " _PSS " , acpi_ns_repair_PSS } ,
{ " _TSS " , acpi_ns_repair_TSS } ,
{ { 0 , 0 , 0 , 0 } , NULL } /* Table terminator */
} ;
2009-12-11 09:53:11 +03:00
# define ACPI_FDE_FIELD_COUNT 5
# define ACPI_FDE_BYTE_BUFFER_SIZE 5
# define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (u32))
2009-11-12 04:44:06 +03:00
/******************************************************************************
*
* FUNCTION : acpi_ns_complex_repairs
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2012-07-12 05:40:10 +04:00
* node - Namespace node for the method / object
2009-11-12 04:44:06 +03:00
* validate_status - Original status of earlier validation
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if repair was successful . If name is not
* matched , validate_status is returned .
*
* DESCRIPTION : Attempt to repair / convert a return object of a type that was
* not expected .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_complex_repairs ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
struct acpi_namespace_node * node ,
acpi_status validate_status ,
union acpi_operand_object * * return_object_ptr )
{
const struct acpi_repair_info * predefined ;
acpi_status status ;
/* Check if this name is in the list of repairable names */
2013-03-08 13:23:03 +04:00
predefined = acpi_ns_match_complex_repair ( node ) ;
2009-11-12 04:44:06 +03:00
if ( ! predefined ) {
return ( validate_status ) ;
}
2013-05-30 06:00:01 +04:00
status = predefined - > repair_function ( info , return_object_ptr ) ;
2009-11-12 04:44:06 +03:00
return ( status ) ;
}
/******************************************************************************
*
2013-03-08 13:23:03 +04:00
* FUNCTION : acpi_ns_match_complex_repair
2009-11-12 04:44:06 +03:00
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : node - Namespace node for the method / object
2009-11-12 04:44:06 +03:00
*
* RETURN : Pointer to entry in repair table . NULL indicates not found .
*
* DESCRIPTION : Check an object name against the repairable object list .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-03-08 13:23:03 +04:00
static const struct acpi_repair_info * acpi_ns_match_complex_repair ( struct
acpi_namespace_node
* node )
2009-11-12 04:44:06 +03:00
{
const struct acpi_repair_info * this_name ;
/* Search info table for a repairable predefined method/object name */
this_name = acpi_ns_repairable_names ;
while ( this_name - > repair_function ) {
if ( ACPI_COMPARE_NAME ( node - > name . ascii , this_name - > name ) ) {
return ( this_name ) ;
}
this_name + + ;
}
return ( NULL ) ; /* Not found */
}
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_ALR
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2009-11-12 04:44:06 +03:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _ALR object . If necessary , sort the object list
* ascending by the ambient illuminance values .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_ALR ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr )
{
union acpi_operand_object * return_object = * return_object_ptr ;
acpi_status status ;
2013-05-30 06:00:01 +04:00
status = acpi_ns_check_sorted_list ( info , return_object , 2 , 1 ,
2009-11-12 04:44:06 +03:00
ACPI_SORT_ASCENDING ,
" AmbientIlluminance " ) ;
return ( status ) ;
}
2009-12-11 09:53:11 +03:00
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_FDE
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2009-12-11 09:53:11 +03:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _FDE and _GTM objects . The expected return
2009-12-11 10:24:27 +03:00
* value is a Buffer of 5 DWORDs . This function repairs a common
* problem where the return value is a Buffer of BYTEs , not
* DWORDs .
2009-12-11 09:53:11 +03:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_FDE ( struct acpi_evaluate_info * info ,
2009-12-11 09:53:11 +03:00
union acpi_operand_object * * return_object_ptr )
{
union acpi_operand_object * return_object = * return_object_ptr ;
union acpi_operand_object * buffer_object ;
u8 * byte_buffer ;
u32 * dword_buffer ;
u32 i ;
2009-12-11 10:23:22 +03:00
ACPI_FUNCTION_NAME ( ns_repair_FDE ) ;
2009-12-11 09:53:11 +03:00
switch ( return_object - > common . type ) {
case ACPI_TYPE_BUFFER :
/* This is the expected type. Length should be (at least) 5 DWORDs */
if ( return_object - > buffer . length > = ACPI_FDE_DWORD_BUFFER_SIZE ) {
return ( AE_OK ) ;
}
/* We can only repair if we have exactly 5 BYTEs */
if ( return_object - > buffer . length ! = ACPI_FDE_BYTE_BUFFER_SIZE ) {
2013-05-30 06:00:01 +04:00
ACPI_WARN_PREDEFINED ( ( AE_INFO , info - > full_pathname ,
info - > node_flags ,
2009-12-11 09:53:11 +03:00
" Incorrect return buffer length %u, expected %u " ,
return_object - > buffer . length ,
ACPI_FDE_DWORD_BUFFER_SIZE ) ) ;
return ( AE_AML_OPERAND_TYPE ) ;
}
/* Create the new (larger) buffer object */
buffer_object =
acpi_ut_create_buffer_object ( ACPI_FDE_DWORD_BUFFER_SIZE ) ;
if ( ! buffer_object ) {
return ( AE_NO_MEMORY ) ;
}
/* Expand each byte to a DWORD */
byte_buffer = return_object - > buffer . pointer ;
dword_buffer =
ACPI_CAST_PTR ( u32 , buffer_object - > buffer . pointer ) ;
for ( i = 0 ; i < ACPI_FDE_FIELD_COUNT ; i + + ) {
* dword_buffer = ( u32 ) * byte_buffer ;
dword_buffer + + ;
byte_buffer + + ;
}
2009-12-11 10:23:22 +03:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_REPAIR ,
" %s Expanded Byte Buffer to expected DWord Buffer \n " ,
2013-05-30 06:00:01 +04:00
info - > full_pathname ) ) ;
2009-12-11 09:53:11 +03:00
break ;
default :
2013-06-08 04:58:14 +04:00
2009-12-11 09:53:11 +03:00
return ( AE_AML_OPERAND_TYPE ) ;
}
/* Delete the original return object, return the new buffer object */
acpi_ut_remove_reference ( return_object ) ;
* return_object_ptr = buffer_object ;
2013-05-30 06:00:01 +04:00
info - > return_flags | = ACPI_OBJECT_REPAIRED ;
2009-12-11 09:53:11 +03:00
return ( AE_OK ) ;
2010-09-15 10:11:02 +04:00
}
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_CID
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2010-09-15 10:11:02 +04:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _CID object . If a string , ensure that all
* letters are uppercase and that there is no leading asterisk .
* If a Package , ensure same for all string elements .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_CID ( struct acpi_evaluate_info * info ,
2010-09-15 10:11:02 +04:00
union acpi_operand_object * * return_object_ptr )
{
acpi_status status ;
union acpi_operand_object * return_object = * return_object_ptr ;
union acpi_operand_object * * element_ptr ;
union acpi_operand_object * original_element ;
u16 original_ref_count ;
u32 i ;
/* Check for _CID as a simple string */
if ( return_object - > common . type = = ACPI_TYPE_STRING ) {
2013-05-30 06:00:01 +04:00
status = acpi_ns_repair_HID ( info , return_object_ptr ) ;
2010-09-15 10:11:02 +04:00
return ( status ) ;
}
/* Exit if not a Package */
if ( return_object - > common . type ! = ACPI_TYPE_PACKAGE ) {
return ( AE_OK ) ;
}
/* Examine each element of the _CID package */
element_ptr = return_object - > package . elements ;
for ( i = 0 ; i < return_object - > package . count ; i + + ) {
original_element = * element_ptr ;
original_ref_count = original_element - > common . reference_count ;
2013-05-30 06:00:01 +04:00
status = acpi_ns_repair_HID ( info , element_ptr ) ;
2010-09-15 10:11:02 +04:00
if ( ACPI_FAILURE ( status ) ) {
return ( status ) ;
}
/* Take care with reference counts */
if ( original_element ! = * element_ptr ) {
/* Element was replaced */
( * element_ptr ) - > common . reference_count =
original_ref_count ;
acpi_ut_remove_reference ( original_element ) ;
}
element_ptr + + ;
}
return ( AE_OK ) ;
}
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_HID
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2010-09-15 10:11:02 +04:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _HID object . If a string , ensure that all
* letters are uppercase and that there is no leading asterisk .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_HID ( struct acpi_evaluate_info * info ,
2010-09-15 10:11:02 +04:00
union acpi_operand_object * * return_object_ptr )
{
union acpi_operand_object * return_object = * return_object_ptr ;
union acpi_operand_object * new_string ;
char * source ;
char * dest ;
ACPI_FUNCTION_NAME ( ns_repair_HID ) ;
/* We only care about string _HID objects (not integers) */
if ( return_object - > common . type ! = ACPI_TYPE_STRING ) {
return ( AE_OK ) ;
}
if ( return_object - > string . length = = 0 ) {
2013-05-30 06:00:01 +04:00
ACPI_WARN_PREDEFINED ( ( AE_INFO , info - > full_pathname ,
info - > node_flags ,
2010-09-15 10:11:02 +04:00
" Invalid zero-length _HID or _CID string " ) ) ;
/* Return AE_OK anyway, let driver handle it */
2013-05-30 06:00:01 +04:00
info - > return_flags | = ACPI_OBJECT_REPAIRED ;
2010-09-15 10:11:02 +04:00
return ( AE_OK ) ;
}
/* It is simplest to always create a new string object */
new_string = acpi_ut_create_string_object ( return_object - > string . length ) ;
if ( ! new_string ) {
return ( AE_NO_MEMORY ) ;
}
/*
* Remove a leading asterisk if present . For some unknown reason , there
* are many machines in the field that contains IDs like this .
*
* Examples : " *PNP0C03 " , " *ACPI0003 "
*/
source = return_object - > string . pointer ;
if ( * source = = ' * ' ) {
source + + ;
new_string - > string . length - - ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_REPAIR ,
" %s: Removed invalid leading asterisk \n " ,
2013-05-30 06:00:01 +04:00
info - > full_pathname ) ) ;
2010-09-15 10:11:02 +04:00
}
/*
2011-11-16 10:59:17 +04:00
* Copy and uppercase the string . From the ACPI 5.0 specification :
2010-09-15 10:11:02 +04:00
*
* A valid PNP ID must be of the form " AAA#### " where A is an uppercase
* letter and # is a hex digit . A valid ACPI ID must be of the form
2011-11-16 10:59:17 +04:00
* " NNNN#### " where N is an uppercase letter or decimal digit , and
* # is a hex digit .
2010-09-15 10:11:02 +04:00
*/
for ( dest = new_string - > string . pointer ; * source ; dest + + , source + + ) {
* dest = ( char ) ACPI_TOUPPER ( * source ) ;
}
acpi_ut_remove_reference ( return_object ) ;
* return_object_ptr = new_string ;
return ( AE_OK ) ;
2009-12-11 09:53:11 +03:00
}
2009-11-12 04:44:06 +03:00
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_TSS
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2009-11-12 04:44:06 +03:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _TSS object . If necessary , sort the object list
* descending by the power dissipation values .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_TSS ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr )
{
union acpi_operand_object * return_object = * return_object_ptr ;
acpi_status status ;
2011-07-04 12:36:16 +04:00
struct acpi_namespace_node * node ;
/*
* We can only sort the _TSS return package if there is no _PSS in the
* same scope . This is because if _PSS is present , the ACPI specification
* dictates that the _TSS Power Dissipation field is to be ignored , and
* therefore some BIOSs leave garbage values in the _TSS Power field ( s ) .
* In this case , it is best to just return the _TSS package as - is .
* ( May , 2011 )
*/
2013-05-30 06:00:01 +04:00
status = acpi_ns_get_node ( info - > node , " ^_PSS " ,
ACPI_NS_NO_UPSEARCH , & node ) ;
2011-07-04 12:36:16 +04:00
if ( ACPI_SUCCESS ( status ) ) {
return ( AE_OK ) ;
}
2009-11-12 04:44:06 +03:00
2013-05-30 06:00:01 +04:00
status = acpi_ns_check_sorted_list ( info , return_object , 5 , 1 ,
2009-11-12 04:44:06 +03:00
ACPI_SORT_DESCENDING ,
" PowerDissipation " ) ;
return ( status ) ;
}
/******************************************************************************
*
* FUNCTION : acpi_ns_repair_PSS
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2009-11-12 04:44:06 +03:00
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN : Status . AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION : Repair for the _PSS object . If necessary , sort the object list
* by the CPU frequencies . Check that the power dissipation values
* are all proportional to CPU frequency ( i . e . , sorting by
* frequency should be the same as sorting by power . )
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_repair_PSS ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * * return_object_ptr )
{
union acpi_operand_object * return_object = * return_object_ptr ;
union acpi_operand_object * * outer_elements ;
u32 outer_element_count ;
union acpi_operand_object * * elements ;
union acpi_operand_object * obj_desc ;
u32 previous_value ;
acpi_status status ;
u32 i ;
/*
* Entries ( sub - packages ) in the _PSS Package must be sorted by power
* dissipation , in descending order . If it appears that the list is
* incorrectly sorted , sort it . We sort by cpu_frequency , since this
* should be proportional to the power .
*/
2013-05-30 06:00:01 +04:00
status = acpi_ns_check_sorted_list ( info , return_object , 6 , 0 ,
2009-11-12 04:44:06 +03:00
ACPI_SORT_DESCENDING ,
" CpuFrequency " ) ;
if ( ACPI_FAILURE ( status ) ) {
return ( status ) ;
}
/*
* We now know the list is correctly sorted by CPU frequency . Check if
* the power dissipation values are proportional .
*/
previous_value = ACPI_UINT32_MAX ;
outer_elements = return_object - > package . elements ;
outer_element_count = return_object - > package . count ;
for ( i = 0 ; i < outer_element_count ; i + + ) {
elements = ( * outer_elements ) - > package . elements ;
obj_desc = elements [ 1 ] ; /* Index1 = power_dissipation */
if ( ( u32 ) obj_desc - > integer . value > previous_value ) {
2013-05-30 06:00:01 +04:00
ACPI_WARN_PREDEFINED ( ( AE_INFO , info - > full_pathname ,
info - > node_flags ,
2009-11-12 04:44:06 +03:00
" SubPackage[%u,%u] - suspicious power dissipation values " ,
i - 1 , i ) ) ;
}
previous_value = ( u32 ) obj_desc - > integer . value ;
outer_elements + + ;
}
return ( AE_OK ) ;
}
/******************************************************************************
*
* FUNCTION : acpi_ns_check_sorted_list
*
2013-05-30 06:00:01 +04:00
* PARAMETERS : info - Method execution information block
2009-11-12 04:44:06 +03:00
* return_object - Pointer to the top - level returned object
* expected_count - Minimum length of each sub - package
* sort_index - Sub - package entry to sort on
* sort_direction - Ascending or descending
* sort_key_name - Name of the sort_index field
*
* RETURN : Status . AE_OK if the list is valid and is sorted correctly or
* has been repaired by sorting the list .
*
* DESCRIPTION : Check if the package list is valid and sorted correctly by the
* sort_index . If not , then sort the list .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_status
2013-05-30 06:00:01 +04:00
acpi_ns_check_sorted_list ( struct acpi_evaluate_info * info ,
2009-11-12 04:44:06 +03:00
union acpi_operand_object * return_object ,
u32 expected_count ,
u32 sort_index ,
u8 sort_direction , char * sort_key_name )
{
u32 outer_element_count ;
union acpi_operand_object * * outer_elements ;
union acpi_operand_object * * elements ;
union acpi_operand_object * obj_desc ;
u32 i ;
u32 previous_value ;
2009-12-11 10:23:22 +03:00
ACPI_FUNCTION_NAME ( ns_check_sorted_list ) ;
2009-11-12 04:44:06 +03:00
/* The top-level object must be a package */
if ( return_object - > common . type ! = ACPI_TYPE_PACKAGE ) {
return ( AE_AML_OPERAND_TYPE ) ;
}
/*
2009-12-11 10:29:44 +03:00
* NOTE : assumes list of sub - packages contains no NULL elements .
* Any NULL elements should have been removed by earlier call
* to acpi_ns_remove_null_elements .
2009-11-12 04:44:06 +03:00
*/
outer_elements = return_object - > package . elements ;
outer_element_count = return_object - > package . count ;
if ( ! outer_element_count ) {
return ( AE_AML_PACKAGE_LIMIT ) ;
}
previous_value = 0 ;
if ( sort_direction = = ACPI_SORT_DESCENDING ) {
previous_value = ACPI_UINT32_MAX ;
}
/* Examine each subpackage */
for ( i = 0 ; i < outer_element_count ; i + + ) {
/* Each element of the top-level package must also be a package */
if ( ( * outer_elements ) - > common . type ! = ACPI_TYPE_PACKAGE ) {
return ( AE_AML_OPERAND_TYPE ) ;
}
/* Each sub-package must have the minimum length */
if ( ( * outer_elements ) - > package . count < expected_count ) {
return ( AE_AML_PACKAGE_LIMIT ) ;
}
elements = ( * outer_elements ) - > package . elements ;
obj_desc = elements [ sort_index ] ;
if ( obj_desc - > common . type ! = ACPI_TYPE_INTEGER ) {
return ( AE_AML_OPERAND_TYPE ) ;
}
/*
* The list must be sorted in the specified order . If we detect a
2010-01-21 04:08:31 +03:00
* discrepancy , sort the entire list .
2009-11-12 04:44:06 +03:00
*/
if ( ( ( sort_direction = = ACPI_SORT_ASCENDING ) & &
( obj_desc - > integer . value < previous_value ) ) | |
( ( sort_direction = = ACPI_SORT_DESCENDING ) & &
( obj_desc - > integer . value > previous_value ) ) ) {
2010-01-21 04:08:31 +03:00
acpi_ns_sort_list ( return_object - > package . elements ,
outer_element_count , sort_index ,
sort_direction ) ;
2009-11-12 04:44:06 +03:00
2013-05-30 06:00:01 +04:00
info - > return_flags | = ACPI_OBJECT_REPAIRED ;
2009-11-12 04:44:06 +03:00
2009-12-11 10:23:22 +03:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_REPAIR ,
" %s: Repaired unsorted list - now sorted by %s \n " ,
2013-05-30 06:00:01 +04:00
info - > full_pathname , sort_key_name ) ) ;
2009-11-12 04:44:06 +03:00
return ( AE_OK ) ;
}
previous_value = ( u32 ) obj_desc - > integer . value ;
outer_elements + + ;
}
return ( AE_OK ) ;
}
/******************************************************************************
*
* FUNCTION : acpi_ns_sort_list
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : elements - Package object element list
* count - Element count for above
* index - Sort by which package element
2009-11-12 04:44:06 +03:00
* sort_direction - Ascending or Descending sort
*
2010-01-21 04:08:31 +03:00
* RETURN : None
2009-11-12 04:44:06 +03:00
*
* DESCRIPTION : Sort the objects that are in a package element list .
*
2010-01-21 04:08:31 +03:00
* NOTE : Assumes that all NULL elements have been removed from the package ,
* and that all elements have been verified to be of type Integer .
2009-11-12 04:44:06 +03:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-01-21 04:08:31 +03:00
static void
2009-11-12 04:44:06 +03:00
acpi_ns_sort_list ( union acpi_operand_object * * elements ,
u32 count , u32 index , u8 sort_direction )
{
union acpi_operand_object * obj_desc1 ;
union acpi_operand_object * obj_desc2 ;
union acpi_operand_object * temp_obj ;
u32 i ;
u32 j ;
/* Simple bubble sort */
for ( i = 1 ; i < count ; i + + ) {
for ( j = ( count - 1 ) ; j > = i ; j - - ) {
obj_desc1 = elements [ j - 1 ] - > package . elements [ index ] ;
obj_desc2 = elements [ j ] - > package . elements [ index ] ;
if ( ( ( sort_direction = = ACPI_SORT_ASCENDING ) & &
( obj_desc1 - > integer . value >
obj_desc2 - > integer . value ) )
| | ( ( sort_direction = = ACPI_SORT_DESCENDING )
& & ( obj_desc1 - > integer . value <
obj_desc2 - > integer . value ) ) ) {
temp_obj = elements [ j - 1 ] ;
elements [ j - 1 ] = elements [ j ] ;
elements [ j ] = temp_obj ;
}
}
}
}