summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig9
-rw-r--r--drivers/acpi/acpi_memhotplug.c18
-rw-r--r--drivers/acpi/acpica/Makefile2
-rw-r--r--drivers/acpi/acpica/utclib.c749
-rw-r--r--drivers/acpi/apei/apei-base.c3
-rw-r--r--drivers/acpi/apei/erst-dbg.c11
-rw-r--r--drivers/acpi/device_pm.c3
-rw-r--r--drivers/acpi/glue.c11
-rw-r--r--drivers/acpi/osl.c204
-rw-r--r--drivers/acpi/pci_bind.c12
-rw-r--r--drivers/acpi/pci_irq.c17
-rw-r--r--drivers/acpi/pci_root.c165
-rw-r--r--drivers/acpi/power.c11
-rw-r--r--drivers/acpi/processor_idle.c4
-rw-r--r--drivers/acpi/processor_perflib.c7
-rw-r--r--drivers/acpi/scan.c2
16 files changed, 348 insertions, 880 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0300bf612946..38c5078da11d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -267,6 +267,15 @@ config ACPI_CUSTOM_DSDT
bool
default ACPI_CUSTOM_DSDT_FILE != ""
+config ACPI_INITRD_TABLE_OVERRIDE
+ bool "ACPI tables can be passed via uncompressed cpio in initrd"
+ default n
+ help
+ This option provides functionality to override arbitrary ACPI tables
+ via initrd. No functional change if no ACPI tables are passed via
+ initrd, therefore it's safe to say Y.
+ See Documentation/acpi/initrd_table_override.txt for details
+
config ACPI_BLACKLIST_YEAR
int "Disable ACPI for systems before Jan 1st this year" if X86_32
default 0
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index eb30e5ab4cab..b679bf8478f7 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -226,16 +226,6 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
struct acpi_memory_info *info;
int node;
-
- /* Get the range from the _CRS */
- result = acpi_memory_get_device_resources(mem_device);
- if (result) {
- dev_err(&mem_device->device->dev,
- "get_device_resources failed\n");
- mem_device->state = MEMORY_INVALID_STATE;
- return result;
- }
-
node = acpi_get_node(mem_device->device->handle);
/*
* Tell the VM there is more memory here...
@@ -342,14 +332,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
break;
}
- if (acpi_memory_check_device(mem_device))
- break;
-
- if (acpi_memory_enable_device(mem_device)) {
- acpi_handle_err(handle,"Cannot enable memory device\n");
- break;
- }
-
ost_code = ACPI_OST_SC_SUCCESS;
break;
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index c8bc24bd1f72..bc7a03ded064 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -162,5 +162,5 @@ acpi-y += \
utxferror.o \
utxfmutex.o
-acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o utclib.o
+acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o
diff --git a/drivers/acpi/acpica/utclib.c b/drivers/acpi/acpica/utclib.c
deleted file mode 100644
index 19ea4755aa73..000000000000
--- a/drivers/acpi/acpica/utclib.c
+++ /dev/null
@@ -1,749 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmclib - Local implementation of C library functions
- *
- *****************************************************************************/
-
-/*
- * Copyright (C) 2000 - 2012, 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/acpi.h>
-#include "accommon.h"
-
-/*
- * These implementations of standard C Library routines can optionally be
- * used if a C library is not available. In general, they are less efficient
- * than an inline or assembly implementation
- */
-
-#define _COMPONENT ACPI_UTILITIES
-ACPI_MODULE_NAME("cmclib")
-
-#ifndef ACPI_USE_SYSTEM_CLIBRARY
-#define NEGATIVE 1
-#define POSITIVE 0
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_memcmp (memcmp)
- *
- * PARAMETERS: buffer1 - First Buffer
- * buffer2 - Second Buffer
- * count - Maximum # of bytes to compare
- *
- * RETURN: Index where Buffers mismatched, or 0 if Buffers matched
- *
- * DESCRIPTION: Compare two Buffers, with a maximum length
- *
- ******************************************************************************/
-int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count)
-{
-
- return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*buffer1 -
- (unsigned char)*buffer2));
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_memcpy (memcpy)
- *
- * PARAMETERS: dest - Target of the copy
- * src - Source buffer to copy
- * count - Number of bytes to copy
- *
- * RETURN: Dest
- *
- * DESCRIPTION: Copy arbitrary bytes of memory
- *
- ******************************************************************************/
-
-void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count)
-{
- char *new = (char *)dest;
- char *old = (char *)src;
-
- while (count) {
- *new = *old;
- new++;
- old++;
- count--;
- }
-
- return (dest);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_memset (memset)
- *
- * PARAMETERS: dest - Buffer to set
- * value - Value to set each byte of memory
- * count - Number of bytes to set
- *
- * RETURN: Dest
- *
- * DESCRIPTION: Initialize a buffer to a known value.
- *
- ******************************************************************************/
-
-void *acpi_ut_memset(void *dest, u8 value, acpi_size count)
-{
- char *new = (char *)dest;
-
- while (count) {
- *new = (char)value;
- new++;
- count--;
- }
-
- return (dest);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strlen (strlen)
- *
- * PARAMETERS: string - Null terminated string
- *
- * RETURN: Length
- *
- * DESCRIPTION: Returns the length of the input string
- *
- ******************************************************************************/
-
-acpi_size acpi_ut_strlen(const char *string)
-{
- u32 length = 0;
-
- /* Count the string until a null is encountered */
-
- while (*string) {
- length++;
- string++;
- }
-
- return (length);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strcpy (strcpy)
- *
- * PARAMETERS: dst_string - Target of the copy
- * src_string - The source string to copy
- *
- * RETURN: dst_string
- *
- * DESCRIPTION: Copy a null terminated string
- *
- ******************************************************************************/
-
-char *acpi_ut_strcpy(char *dst_string, const char *src_string)
-{
- char *string = dst_string;
-
- /* Move bytes brute force */
-
- while (*src_string) {
- *string = *src_string;
-
- string++;
- src_string++;
- }
-
- /* Null terminate */
-
- *string = 0;
- return (dst_string);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strncpy (strncpy)
- *
- * PARAMETERS: dst_string - Target of the copy
- * src_string - The source string to copy
- * count - Maximum # of bytes to copy
- *
- * RETURN: dst_string
- *
- * DESCRIPTION: Copy a null terminated string, with a maximum length
- *
- ******************************************************************************/
-
-char *acpi_ut_strncpy(char *dst_string, const char *src_string, acpi_size count)
-{
- char *string = dst_string;
-
- /* Copy the string */
-
- for (string = dst_string;
- count && (count--, (*string++ = *src_string++));) {;
- }
-
- /* Pad with nulls if necessary */
-
- while (count--) {
- *string = 0;
- string++;
- }
-
- /* Return original pointer */
-
- return (dst_string);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strcmp (strcmp)
- *
- * PARAMETERS: string1 - First string
- * string2 - Second string
- *
- * RETURN: Index where strings mismatched, or 0 if strings matched
- *
- * DESCRIPTION: Compare two null terminated strings
- *
- ******************************************************************************/
-
-int acpi_ut_strcmp(const char *string1, const char *string2)
-{
-
- for (; (*string1 == *string2); string2++) {
- if (!*string1++) {
- return (0);
- }
- }
-
- return ((unsigned char)*string1 - (unsigned char)*string2);
-}
-
-#ifdef ACPI_FUTURE_IMPLEMENTATION
-/* Not used at this time */
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strchr (strchr)
- *
- * PARAMETERS: string - Search string
- * ch - character to search for
- *
- * RETURN: Ptr to char or NULL if not found
- *
- * DESCRIPTION: Search a string for a character
- *
- ******************************************************************************/
-
-char *acpi_ut_strchr(const char *string, int ch)
-{
-
- for (; (*string); string++) {
- if ((*string) == (char)ch) {
- return ((char *)string);
- }
- }
-
- return (NULL);
-}
-#endif
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strncmp (strncmp)
- *
- * PARAMETERS: string1 - First string
- * string2 - Second string
- * count - Maximum # of bytes to compare
- *
- * RETURN: Index where strings mismatched, or 0 if strings matched
- *
- * DESCRIPTION: Compare two null terminated strings, with a maximum length
- *
- ******************************************************************************/
-
-int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count)
-{
-
- for (; count-- && (*string1 == *string2); string2++) {
- if (!*string1++) {
- return (0);
- }
- }
-
- return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*string1 -
- (unsigned char)*string2));
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strcat (Strcat)
- *
- * PARAMETERS: dst_string - Target of the copy
- * src_string - The source string to copy
- *
- * RETURN: dst_string
- *
- * DESCRIPTION: Append a null terminated string to a null terminated string
- *
- ******************************************************************************/
-
-char *acpi_ut_strcat(char *dst_string, const char *src_string)
-{
- char *string;
-
- /* Find end of the destination string */
-
- for (string = dst_string; *string++;) {;
- }
-
- /* Concatenate the string */
-
- for (--string; (*string++ = *src_string++);) {;
- }
-
- return (dst_string);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strncat (strncat)
- *
- * PARAMETERS: dst_string - Target of the copy
- * src_string - The source string to copy
- * count - Maximum # of bytes to copy
- *
- * RETURN: dst_string
- *
- * DESCRIPTION: Append a null terminated string to a null terminated string,
- * with a maximum count.
- *
- ******************************************************************************/
-
-char *acpi_ut_strncat(char *dst_string, const char *src_string, acpi_size count)
-{
- char *string;
-
- if (count) {
-
- /* Find end of the destination string */
-
- for (string = dst_string; *string++;) {;
- }
-
- /* Concatenate the string */
-
- for (--string; (*string++ = *src_string++) && --count;) {;
- }
-
- /* Null terminate if necessary */
-
- if (!count) {
- *string = 0;
- }
- }
-
- return (dst_string);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strstr (strstr)
- *
- * PARAMETERS: string1 - Target string
- * string2 - Substring to search for
- *
- * RETURN: Where substring match starts, Null if no match found
- *
- * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
- * full implementation of strstr, only sufficient for command
- * matching
- *
- ******************************************************************************/
-
-char *acpi_ut_strstr(char *string1, char *string2)
-{
- char *string;
-
- if (acpi_ut_strlen(string2) > acpi_ut_strlen(string1)) {
- return (NULL);
- }
-
- /* Walk entire string, comparing the letters */
-
- for (string = string1; *string2;) {
- if (*string2 != *string) {
- return (NULL);
- }
-
- string2++;
- string++;
- }
-
- return (string1);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_strtoul (strtoul)
- *
- * PARAMETERS: string - Null terminated string
- * terminater - Where a pointer to the terminating byte is
- * returned
- * base - Radix of the string
- *
- * RETURN: Converted value
- *
- * DESCRIPTION: Convert a string into a 32-bit unsigned value.
- * Note: use acpi_ut_strtoul64 for 64-bit integers.
- *
- ******************************************************************************/
-
-u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base)
-{
- u32 converted = 0;
- u32 index;
- u32 sign;
- const char *string_start;
- u32 return_value = 0;
- acpi_status status = AE_OK;
-
- /*
- * Save the value of the pointer to the buffer's first
- * character, save the current errno value, and then
- * skip over any white space in the buffer:
- */
- string_start = string;
- while (ACPI_IS_SPACE(*string) || *string == '\t') {
- ++string;
- }
-
- /*
- * The buffer may contain an optional plus or minus sign.
- * If it does, then skip over it but remember what is was:
- */
- if (*string == '-') {
- sign = NEGATIVE;
- ++string;
- } else if (*string == '+') {
- ++string;
- sign = POSITIVE;
- } else {
- sign = POSITIVE;
- }
-
- /*
- * If the input parameter Base is zero, then we need to
- * determine if it is octal, decimal, or hexadecimal:
- */
- if (base == 0) {
- if (*string == '0') {
- if (acpi_ut_to_lower(*(++string)) == 'x') {
- base = 16;
- ++string;
- } else {
- base = 8;
- }
- } else {
- base = 10;
- }
- } else if (base < 2 || base > 36) {
- /*
- * The specified Base parameter is not in the domain of
- * this function:
- */
- goto done;
- }
-
- /*
- * For octal and hexadecimal bases, skip over the leading
- * 0 or 0x, if they are present.
- */
- if (base == 8 && *string == '0') {
- string++;
- }
-
- if (base == 16 &&
- *string == '0' && acpi_ut_to_lower(*(++string)) == 'x') {
- string++;
- }
-
- /*
- * Main loop: convert the string to an unsigned long:
- */
- while (*string) {
- if (ACPI_IS_DIGIT(*string)) {
- index = (u32)((u8)*string - '0');
- } else {
- index = (u32)acpi_ut_to_upper(*string);
- if (ACPI_IS_UPPER(index)) {
- index = index - 'A' + 10;
- } else {
- goto done;
- }
- }
-
- if (index >= base) {
- goto done;
- }
-
- /*
- * Check to see if value is out of range:
- */
-
- if (return_value > ((ACPI_UINT32_MAX - (u32)index) / (u32)base)) {
- status = AE_ERROR;
- return_value = 0; /* reset */
- } else {
- return_value *= base;
- return_value += index;
- converted = 1;
- }
-
- ++string;
- }
-
- done:
- /*
- * If appropriate, update the caller's pointer to the next
- * unconverted character in the buffer.
- */
- if (terminator) {
- if (converted == 0 && return_value == 0 && string != NULL) {
- *terminator = (char *)string_start;
- } else {
- *terminator = (char *)string;
- }
- }
-
- if (status == AE_ERROR) {
- return_value = ACPI_UINT32_MAX;
- }
-
- /*
- * If a minus sign was present, then "the conversion is negated":
- */
- if (sign == NEGATIVE) {
- return_value = (ACPI_UINT32_MAX - return_value) + 1;
- }
-
- return (return_value);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_to_upper (TOUPPER)
- *
- * PARAMETERS: c - Character to convert
- *
- * RETURN: Converted character as an int
- *
- * DESCRIPTION: Convert character to uppercase
- *
- ******************************************************************************/
-
-int acpi_ut_to_upper(int c)
-{
-
- return (ACPI_IS_LOWER(c) ? ((c) - 0x20) : (c));
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_to_lower (TOLOWER)
- *
- * PARAMETERS: c - Character to convert
- *
- * RETURN: Converted character as an int
- *
- * DESCRIPTION: Convert character to lowercase
- *
- ******************************************************************************/
-
-int acpi_ut_to_lower(int c)
-{
-
- return (ACPI_IS_UPPER(c) ? ((c) + 0x20) : (c));
-}
-
-/*******************************************************************************
- *
- * FUNCTION: is* functions
- *
- * DESCRIPTION: is* functions use the ctype table below
- *
- ******************************************************************************/
-
-const u8 _acpi_ctype[257] = {
- _ACPI_CN, /* 0x00 0 NUL */
- _ACPI_CN, /* 0x01 1 SOH */
- _ACPI_CN, /* 0x02 2 STX */
- _ACPI_CN, /* 0x03 3 ETX */
- _ACPI_CN, /* 0x04 4 EOT */
- _ACPI_CN, /* 0x05 5 ENQ */
- _ACPI_CN, /* 0x06 6 ACK */
- _ACPI_CN, /* 0x07 7 BEL */
- _ACPI_CN, /* 0x08 8 BS */
- _ACPI_CN | _ACPI_SP, /* 0x09 9 TAB */
- _ACPI_CN | _ACPI_SP, /* 0x0A 10 LF */
- _ACPI_CN | _ACPI_SP, /* 0x0B 11 VT */
- _ACPI_CN | _ACPI_SP, /* 0x0C 12 FF */
- _ACPI_CN | _ACPI_SP, /* 0x0D 13 CR */
- _ACPI_CN, /* 0x0E 14 SO */
- _ACPI_CN, /* 0x0F 15 SI */
- _ACPI_CN, /* 0x10 16 DLE */
- _ACPI_CN, /* 0x11 17 DC1 */
- _ACPI_CN, /* 0x12 18 DC2 */
- _ACPI_CN, /* 0x13 19 DC3 */
- _ACPI_CN, /* 0x14 20 DC4 */
- _ACPI_CN, /* 0x15 21 NAK */
- _ACPI_CN, /* 0x16 22 SYN */
- _ACPI_CN, /* 0x17 23 ETB */
- _ACPI_CN, /* 0x18 24 CAN */
- _ACPI_CN, /* 0x19 25 EM */
- _ACPI_CN, /* 0x1A 26 SUB */
- _ACPI_CN, /* 0x1B 27 ESC */
- _ACPI_CN, /* 0x1C 28 FS */
- _ACPI_CN, /* 0x1D 29 GS */
- _ACPI_CN, /* 0x1E 30 RS */
- _ACPI_CN, /* 0x1F 31 US */
- _ACPI_XS | _ACPI_SP, /* 0x20 32 ' ' */
- _ACPI_PU, /* 0x21 33 '!' */
- _ACPI_PU, /* 0x22 34 '"' */
- _ACPI_PU, /* 0x23 35 '#' */
- _ACPI_PU, /* 0x24 36 '$' */
- _ACPI_PU, /* 0x25 37 '%' */
- _ACPI_PU, /* 0x26 38 '&' */
- _ACPI_PU, /* 0x27 39 ''' */
- _ACPI_PU, /* 0x28 40 '(' */
- _ACPI_PU, /* 0x29 41 ')' */
- _ACPI_PU, /* 0x2A 42 '*' */
- _ACPI_PU, /* 0x2B 43 '+' */
- _ACPI_PU, /* 0x2C 44 ',' */
- _ACPI_PU, /* 0x2D 45 '-' */
- _ACPI_PU, /* 0x2E 46 '.' */
- _ACPI_PU, /* 0x2F 47 '/' */
- _ACPI_XD | _ACPI_DI, /* 0x30 48 '0' */
- _ACPI_XD | _ACPI_DI, /* 0x31 49 '1' */
- _ACPI_XD | _ACPI_DI, /* 0x32 50 '2' */
- _ACPI_XD | _ACPI_DI, /* 0x33 51 '3' */
- _ACPI_XD | _ACPI_DI, /* 0x34 52 '4' */
- _ACPI_XD | _ACPI_DI, /* 0x35 53 '5' */
- _ACPI_XD | _ACPI_DI, /* 0x36 54 '6' */
- _ACPI_XD | _ACPI_DI, /* 0x37 55 '7' */
- _ACPI_XD | _ACPI_DI, /* 0x38 56 '8' */
- _ACPI_XD | _ACPI_DI, /* 0x39 57 '9' */
- _ACPI_PU, /* 0x3A 58 ':' */
- _ACPI_PU, /* 0x3B 59 ';' */
- _ACPI_PU, /* 0x3C 60 '<' */
- _ACPI_PU, /* 0x3D 61 '=' */
- _ACPI_PU, /* 0x3E 62 '>' */
- _ACPI_PU, /* 0x3F 63 '?' */
- _ACPI_PU, /* 0x40 64 '@' */
- _ACPI_XD | _ACPI_UP, /* 0x41 65 'A' */
- _ACPI_XD | _ACPI_UP, /* 0x42 66 'B' */
- _ACPI_XD | _ACPI_UP, /* 0x43 67 'C' */
- _ACPI_XD | _ACPI_UP, /* 0x44 68 'D' */
- _ACPI_XD | _ACPI_UP, /* 0x45 69 'E' */
- _ACPI_XD | _ACPI_UP, /* 0x46 70 'F' */
- _ACPI_UP, /* 0x47 71 'G' */
- _ACPI_UP, /* 0x48 72 'H' */
- _ACPI_UP, /* 0x49 73 'I' */
- _ACPI_UP, /* 0x4A 74 'J' */
- _ACPI_UP, /* 0x4B 75 'K' */
- _ACPI_UP, /* 0x4C 76 'L' */
- _ACPI_UP, /* 0x4D 77 'M' */
- _ACPI_UP, /* 0x4E 78 'N' */
- _ACPI_UP, /* 0x4F 79 'O' */
- _ACPI_UP, /* 0x50 80 'P' */
- _ACPI_UP, /* 0x51 81 'Q' */
- _ACPI_UP, /* 0x52 82 'R' */
- _ACPI_UP, /* 0x53 83 'S' */
- _ACPI_UP, /* 0x54 84 'T' */
- _ACPI_UP, /* 0x55 85 'U' */
- _ACPI_UP, /* 0x56 86 'V' */
- _ACPI_UP, /* 0x57 87 'W' */
- _ACPI_UP, /* 0x58 88 'X' */
- _ACPI_UP, /* 0x59 89 'Y' */
- _ACPI_UP, /* 0x5A 90 'Z' */
- _ACPI_PU, /* 0x5B 91 '[' */
- _ACPI_PU, /* 0x5C 92 '\' */
- _ACPI_PU, /* 0x5D 93 ']' */
- _ACPI_PU, /* 0x5E 94 '^' */
- _ACPI_PU, /* 0x5F 95 '_' */
- _ACPI_PU, /* 0x60 96 '`' */
- _ACPI_XD | _ACPI_LO, /* 0x61 97 'a' */
- _ACPI_XD | _ACPI_LO, /* 0x62 98 'b' */
- _ACPI_XD | _ACPI_LO, /* 0x63 99 'c' */
- _ACPI_XD | _ACPI_LO, /* 0x64 100 'd' */
- _ACPI_XD | _ACPI_LO, /* 0x65 101 'e' */
- _ACPI_XD | _ACPI_LO, /* 0x66 102 'f' */
- _ACPI_LO, /* 0x67 103 'g' */
- _ACPI_LO, /* 0x68 104 'h' */
- _ACPI_LO, /* 0x69 105 'i' */
- _ACPI_LO, /* 0x6A 106 'j' */
- _ACPI_LO, /* 0x6B 107 'k' */
- _ACPI_LO, /* 0x6C 108 'l' */
- _ACPI_LO, /* 0x6D 109 'm' */
- _ACPI_LO, /* 0x6E 110 'n' */
- _ACPI_LO, /* 0x6F 111 'o' */
- _ACPI_LO, /* 0x70 112 'p' */
- _ACPI_LO, /* 0x71 113 'q' */
- _ACPI_LO, /* 0x72 114 'r' */
- _ACPI_LO, /* 0x73 115 's' */
- _ACPI_LO, /* 0x74 116 't' */
- _ACPI_LO, /* 0x75 117 'u' */
- _ACPI_LO, /* 0x76 118 'v' */
- _ACPI_LO, /* 0x77 119 'w' */
- _ACPI_LO, /* 0x78 120 'x' */
- _ACPI_LO, /* 0x79 121 'y' */
- _ACPI_LO, /* 0x7A 122 'z' */
- _ACPI_PU, /* 0x7B 123 '{' */
- _ACPI_PU, /* 0x7C 124 '|' */
- _ACPI_PU, /* 0x7D 125 '}' */
- _ACPI_PU, /* 0x7E 126 '~' */
- _ACPI_CN, /* 0x7F 127 DEL */
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 to 0x8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 to 0x9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 to 0xAF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 to 0xBF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 to 0xCF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 to 0xDF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 to 0xEF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 to 0xFF */
- 0 /* 0x100 */
-};
-
-#endif /* ACPI_USE_SYSTEM_CLIBRARY */
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 00a783661d0b..46f80e2c92f7 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 &&
*access_bit_width < 32)
*access_bit_width = 32;
+ else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 &&
+ *access_bit_width < 64)
+ *access_bit_width = 64;
if ((bit_width + bit_offset) > *access_bit_width) {
pr_warning(FW_BUG APEI_PFX
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
index 903549df809b..04ab5c9d3ced 100644
--- a/drivers/acpi/apei/erst-dbg.c
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -111,8 +111,17 @@ retry_next:
if (rc)
goto out;
/* no more record */
- if (id == APEI_ERST_INVALID_RECORD_ID)
+ if (id == APEI_ERST_INVALID_RECORD_ID) {
+ /*
+ * If the persistent store is empty initially, the function
+ * 'erst_read' below will return "-ENOENT" value. This causes
+ * 'retry_next' label is entered again. The returned value
+ * should be zero indicating the read operation is EOF.
+ */
+ len = 0;
+
goto out;
+ }
retry:
rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len);
/* The record may be cleared by others, try read next record */
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index f09dc987cf17..c6ff606c6d5b 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -358,8 +358,7 @@ static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
- return handle && ACPI_SUCCESS(acpi_bus_get_device(handle, &adev)) ?
- adev : NULL;
+ return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL;
}
/**
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 01551840d236..35da18113216 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -18,9 +18,14 @@
#define ACPI_GLUE_DEBUG 0
#if ACPI_GLUE_DEBUG
-#define DBG(x...) printk(PREFIX x)
+#define DBG(fmt, ...) \
+ printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__)
#else
-#define DBG(x...) do { } while(0)
+#define DBG(fmt, ...) \
+do { \
+ if (0) \
+ printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__); \
+} while (0)
#endif
static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem);
@@ -292,7 +297,7 @@ static int acpi_platform_notify(struct device *dev)
if (!ret) {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
+ acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer);
DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
kfree(buffer.pointer);
} else
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6dc4a2b1e956..bd22f8667eed 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
return acpi_rsdp;
#endif
- if (efi_enabled) {
+ if (efi_enabled(EFI_CONFIG_TABLES)) {
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
@@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
return AE_OK;
}
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+#include <linux/earlycpio.h>
+#include <linux/memblock.h>
+
+static u64 acpi_tables_addr;
+static int all_tables_size;
+
+/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
+u8 __init acpi_table_checksum(u8 *buffer, u32 length)
+{
+ u8 sum = 0;
+ u8 *end = buffer + length;
+
+ while (buffer < end)
+ sum = (u8) (sum + *(buffer++));
+ return sum;
+}
+
+/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
+static const char * const table_sigs[] = {
+ ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
+ ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
+ ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
+ ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
+ ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
+ ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
+ ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
+ ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+ ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
+
+/* Non-fatal errors: Affected tables/files are ignored */
+#define INVALID_TABLE(x, path, name) \
+ { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+
+#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
+
+/* Must not increase 10 or needs code modification below */
+#define ACPI_OVERRIDE_TABLES 10
+
+void __init acpi_initrd_override(void *data, size_t size)
+{
+ int sig, no, table_nr = 0, total_offset = 0;
+ long offset = 0;
+ struct acpi_table_header *table;
+ char cpio_path[32] = "kernel/firmware/acpi/";
+ struct cpio_data file;
+ struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
+ char *p;
+
+ if (data == NULL || size == 0)
+ return;
+
+ for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+ file = find_cpio_data(cpio_path, data, size, &offset);
+ if (!file.data)
+ break;
+
+ data += offset;
+ size -= offset;
+
+ if (file.size < sizeof(struct acpi_table_header))
+ INVALID_TABLE("Table smaller than ACPI header",
+ cpio_path, file.name);
+
+ table = file.data;
+
+ for (sig = 0; table_sigs[sig]; sig++)
+ if (!memcmp(table->signature, table_sigs[sig], 4))
+ break;
+
+ if (!table_sigs[sig])
+ INVALID_TABLE("Unknown signature",
+ cpio_path, file.name);
+ if (file.size != table->length)
+ INVALID_TABLE("File length does not match table length",
+ cpio_path, file.name);
+ if (acpi_table_checksum(file.data, table->length))
+ INVALID_TABLE("Bad table checksum",
+ cpio_path, file.name);
+
+ pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
+ table->signature, cpio_path, file.name, table->length);
+
+ all_tables_size += table->length;
+ early_initrd_files[table_nr].data = file.data;
+ early_initrd_files[table_nr].size = file.size;
+ table_nr++;
+ }
+ if (table_nr == 0)
+ return;
+
+ acpi_tables_addr =
+ memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+ all_tables_size, PAGE_SIZE);
+ if (!acpi_tables_addr) {
+ WARN_ON(1);
+ return;
+ }
+ /*
+ * Only calling e820_add_reserve does not work and the
+ * tables are invalid (memory got used) later.
+ * memblock_reserve works as expected and the tables won't get modified.
+ * But it's not enough on X86 because ioremap will
+ * complain later (used by acpi_os_map_memory) that the pages
+ * that should get mapped are not marked "reserved".
+ * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
+ * works fine.
+ */
+ memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
+ arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
+
+ p = early_ioremap(acpi_tables_addr, all_tables_size);
+
+ for (no = 0; no < table_nr; no++) {
+ memcpy(p + total_offset, early_initrd_files[no].data,
+ early_initrd_files[no].size);
+ total_offset += early_initrd_files[no].size;
+ }
+ early_iounmap(p, all_tables_size);
+}
+#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
+
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+ pr_warn(PREFIX
+ "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+ table->signature, table->oem_table_id);
+ add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+}
+
+
acpi_status
acpi_os_table_override(struct acpi_table_header * existing_table,
struct acpi_table_header ** new_table)
@@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
*new_table = (struct acpi_table_header *)AmlCode;
#endif
- if (*new_table != NULL) {
- printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
- "this is unsafe: tainting kernel\n",
- existing_table->signature,
- existing_table->oem_table_id);
- add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
- }
+ if (*new_table != NULL)
+ acpi_table_taint(existing_table);
return AE_OK;
}
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
- acpi_physical_address * new_address,
- u32 *new_table_length)
+ acpi_physical_address *address,
+ u32 *table_length)
{
- return AE_SUPPORT;
-}
+#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+ *table_length = 0;
+ *address = 0;
+ return AE_OK;
+#else
+ int table_offset = 0;
+ struct acpi_table_header *table;
+
+ *table_length = 0;
+ *address = 0;
+
+ if (!acpi_tables_addr)
+ return AE_OK;
+
+ do {
+ if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
+ WARN_ON(1);
+ return AE_OK;
+ }
+ table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+ ACPI_HEADER_SIZE);
+
+ if (table_offset + table->length > all_tables_size) {
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ WARN_ON(1);
+ return AE_OK;
+ }
+
+ table_offset += table->length;
+
+ if (memcmp(existing_table->signature, table->signature, 4)) {
+ acpi_os_unmap_memory(table,
+ ACPI_HEADER_SIZE);
+ continue;
+ }
+
+ /* Only override tables with matching oem id */
+ if (memcmp(table->oem_table_id, existing_table->oem_table_id,
+ ACPI_OEM_TABLE_ID_SIZE)) {
+ acpi_os_unmap_memory(table,
+ ACPI_HEADER_SIZE);
+ continue;
+ }
+
+ table_offset -= table->length;
+ *table_length = table->length;
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ *address = acpi_tables_addr + table_offset;
+ break;
+ } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+
+ if (*address != 0)
+ acpi_table_taint(existing_table);
+ return AE_OK;
+#endif
+}
static irqreturn_t acpi_irq(int irq, void *dev_id)
{
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 2ef04098cc1d..a1dee29beed3 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
device_set_run_wake(&dev->dev, false);
pci_acpi_remove_pm_notifier(device);
+ acpi_power_resource_unregister_device(&dev->dev, device->handle);
if (!dev->subordinate)
goto out;
- acpi_pci_irq_del_prt(dev->subordinate);
+ acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
device->ops.bind = NULL;
device->ops.unbind = NULL;
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
{
acpi_status status;
acpi_handle handle;
- struct pci_bus *bus;
+ unsigned char bus;
struct pci_dev *dev;
dev = acpi_get_pci_dev(device->handle);
@@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
return 0;
pci_acpi_add_pm_notifier(device, dev);
+ acpi_power_resource_register_device(&dev->dev, device->handle);
if (device->wakeup.flags.run_wake)
device_set_run_wake(&dev->dev, true);
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
goto out;
if (dev->subordinate)
- bus = dev->subordinate;
+ bus = dev->subordinate->number;
else
- bus = dev->bus;
+ bus = dev->bus->number;
- acpi_pci_irq_add_prt(device->handle, bus);
+ acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
out:
pci_dev_put(dev);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 23a032490130..68a921d03247 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
}
}
-static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
struct acpi_pci_routing_table *prt)
{
struct acpi_prt_entry *entry;
@@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
* 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
* it here.
*/
- entry->id.segment = pci_domain_nr(bus);
- entry->id.bus = bus->number;
+ entry->id.segment = segment;
+ entry->id.bus = bus;
entry->id.device = (prt->address >> 16) & 0xFFFF;
entry->pin = prt->pin + 1;
@@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
return 0;
}
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
entry = buffer.pointer;
while (entry && (entry->length > 0)) {
- acpi_pci_irq_add_entry(handle, bus, entry);
+ acpi_pci_irq_add_entry(handle, segment, bus, entry);
entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length);
}
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
return 0;
}
-void acpi_pci_irq_del_prt(struct pci_bus *bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
{
struct acpi_prt_entry *entry, *tmp;
printk(KERN_DEBUG
"ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
- pci_domain_nr(bus), bus->number);
+ segment, bus);
spin_lock(&acpi_prt_lock);
list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
- if (pci_domain_nr(bus) == entry->id.segment
- && bus->number == entry->id.bus) {
+ if (segment == entry->id.segment && bus == entry->id.bus) {
list_del(&entry->list);
kfree(entry);
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index f70b9e5fc1b5..7928d4dc7056 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_handle handle;
struct acpi_device *child;
u32 flags, base_flags;
+ bool is_osc_granted = false;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
@@ -501,85 +502,47 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
- root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
-
- /*
- * All supported architectures that use ACPI have support for
- * PCI domains, so we indicate this in _OSC support capabilities.
- */
- flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
- acpi_pci_osc_support(root, flags);
-
- /*
- * TBD: Need PCI interface for enumeration/configuration of roots.
- */
-
- mutex_lock(&acpi_pci_root_lock);
- list_add_tail(&root->node, &acpi_pci_roots);
- mutex_unlock(&acpi_pci_root_lock);
-
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
/*
- * Scan the Root Bridge
- * --------------------
- * Must do this prior to any attempt to bind the root device, as the
- * PCI namespace does not get created until this call is made (and
- * thus the root bridge's pci_dev does not exist).
- */
- root->bus = pci_acpi_scan_root(root);
- if (!root->bus) {
- printk(KERN_ERR PREFIX
- "Bus %04x:%02x not present in PCI namespace\n",
- root->segment, (unsigned int)root->secondary.start);
- result = -ENODEV;
- goto out_del_root;
- }
-
- /*
- * Attach ACPI-PCI Context
- * -----------------------
- * Thus binding the ACPI and PCI devices.
- */
- result = acpi_pci_bind_root(device);
- if (result)
- goto out_del_root;
-
- /*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists.
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
- result = acpi_pci_irq_add_prt(device->handle, root->bus);
+ result = acpi_pci_irq_add_prt(device->handle, root->segment,
+ root->secondary.start);
+
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
/*
- * Scan and bind all _ADR-Based Devices
+ * All supported architectures that use ACPI have support for
+ * PCI domains, so we indicate this in _OSC support capabilities.
*/
- list_for_each_entry(child, &device->children, node)
- acpi_pci_bridge_scan(child);
+ flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+ acpi_pci_osc_support(root, flags);
/* Indicate support for various _OSC capabilities. */
- if (pci_ext_cfg_avail(root->bus->self))
+ if (pci_ext_cfg_avail())
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
- if (pcie_aspm_support_enabled())
+ if (pcie_aspm_support_enabled()) {
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
- OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+ }
if (pci_msi_enabled())
flags |= OSC_MSI_SUPPORT;
if (flags != base_flags) {
status = acpi_pci_osc_support(root, flags);
if (ACPI_FAILURE(status)) {
- dev_info(root->bus->bridge, "ACPI _OSC support "
+ dev_info(&device->dev, "ACPI _OSC support "
"notification failed, disabling PCIe ASPM\n");
pcie_no_aspm();
flags = base_flags;
}
}
-
if (!pcie_ports_disabled
&& (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device)
if (pci_aer_available()) {
if (aer_acpi_firmware_first())
- dev_dbg(root->bus->bridge,
+ dev_dbg(&device->dev,
"PCIe errors handled by BIOS.\n");
else
flags |= OSC_PCI_EXPRESS_AER_CONTROL;
}
- dev_info(root->bus->bridge,
+ dev_info(&device->dev,
"Requesting ACPI _OSC control (0x%02x)\n", flags);
status = acpi_pci_osc_control_set(device->handle, &flags,
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_SUCCESS(status)) {
- dev_info(root->bus->bridge,
+ is_osc_granted = true;
+ dev_info(&device->dev,
"ACPI _OSC control (0x%02x) granted\n", flags);
- if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
- /*
- * We have ASPM control, but the FADT indicates
- * that it's unsupported. Clear it.
- */
- pcie_clear_aspm(root->bus);
- }
} else {
- dev_info(root->bus->bridge,
+ is_osc_granted = false;
+ dev_info(&device->dev,
"ACPI _OSC request failed (%s), "
"returned control mask: 0x%02x\n",
acpi_format_exception(status), flags);
- pr_info("ACPI _OSC control for PCIe not granted, "
- "disabling ASPM\n");
- pcie_no_aspm();
}
} else {
- dev_info(root->bus->bridge,
- "Unable to request _OSC control "
- "(_OSC support mask: 0x%02x)\n", flags);
+ dev_info(&device->dev,
+ "Unable to request _OSC control "
+ "(_OSC support mask: 0x%02x)\n", flags);
+ }
+
+ /*
+ * TBD: Need PCI interface for enumeration/configuration of roots.
+ */
+
+ mutex_lock(&acpi_pci_root_lock);
+ list_add_tail(&root->node, &acpi_pci_roots);
+ mutex_unlock(&acpi_pci_root_lock);
+
+ /*
+ * Scan the Root Bridge
+ * --------------------
+ * Must do this prior to any attempt to bind the root device, as the
+ * PCI namespace does not get created until this call is made (and
+ * thus the root bridge's pci_dev does not exist).
+ */
+ root->bus = pci_acpi_scan_root(root);
+ if (!root->bus) {
+ printk(KERN_ERR PREFIX
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->segment, (unsigned int)root->secondary.start);
+ result = -ENODEV;
+ goto out_del_root;
+ }
+
+ /*
+ * Attach ACPI-PCI Context
+ * -----------------------
+ * Thus binding the ACPI and PCI devices.
+ */
+ result = acpi_pci_bind_root(device);
+ if (result)
+ goto out_del_root;
+
+ /*
+ * Scan and bind all _ADR-Based Devices
+ */
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+
+ /* ASPM setting */
+ if (is_osc_granted) {
+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
+ pcie_clear_aspm(root->bus);
+ } else {
+ pr_info("ACPI _OSC control for PCIe not granted, "
+ "disabling ASPM\n");
+ pcie_no_aspm();
}
pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -634,6 +638,8 @@ out_del_root:
mutex_lock(&acpi_pci_root_lock);
list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock);
+
+ acpi_pci_irq_del_prt(root->segment, root->secondary.start);
end:
kfree(root);
return result;
@@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
struct acpi_pci_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver;
+ if (system_state != SYSTEM_BOOTING)
+ pci_assign_unassigned_bus_resources(root->bus);
+
mutex_lock(&acpi_pci_root_lock);
list_for_each_entry(driver, &acpi_pci_drivers, node)
if (driver->add)
driver->add(root);
mutex_unlock(&acpi_pci_root_lock);
+ /* need to after hot-added ioapic is registered */
+ if (system_state != SYSTEM_BOOTING)
+ pci_enable_bridges(root->bus);
+
pci_bus_add_devices(root->bus);
return 0;
@@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
static int acpi_pci_root_remove(struct acpi_device *device, int type)
{
+ acpi_status status;
+ acpi_handle handle;
struct acpi_pci_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver;
+ pci_stop_root_bus(root->bus);
+
mutex_lock(&acpi_pci_root_lock);
- list_for_each_entry(driver, &acpi_pci_drivers, node)
+ list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
if (driver->remove)
driver->remove(root);
+ mutex_unlock(&acpi_pci_root_lock);
device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device);
+ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+ if (ACPI_SUCCESS(status))
+ acpi_pci_irq_del_prt(root->segment, root->secondary.start);
+
+ pci_remove_root_bus(root->bus);
+
+ mutex_lock(&acpi_pci_root_lock);
list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock);
kfree(root);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 7db61b8fa11f..6e7b9d523812 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -445,11 +445,8 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
return -ENODEV;
ret = acpi_bus_get_device(handle, &acpi_dev);
- if (ret)
- goto no_power_resource;
-
- if (!acpi_dev->power.flags.power_resources)
- goto no_power_resource;
+ if (ret || !acpi_dev->power.flags.power_resources)
+ return -ENODEV;
powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL);
if (!powered_device)
@@ -471,10 +468,6 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
}
return ret;
-
-no_power_resource:
- printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!\n");
- return -ENODEV;
}
EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f1a5da44591d..ed9a1cc690be 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
return -EINVAL;
}
+ if (!dev)
+ return -EINVAL;
+
dev->cpu = pr->id;
if (max_cstate == 0)
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
}
/* Populate Updated C-state information */
+ acpi_processor_get_power_info(pr);
acpi_processor_setup_cpuidle_states(pr);
/* Enable all cpuidle devices */
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 836bfe069042..53e7ac9403a7 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
|| boot_cpu_data.x86 == 0x11) {
rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
+ /*
+ * MSR C001_0064+:
+ * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
+ */
+ if (!(hi & BIT(31)))
+ return;
+
fid = lo & 0x3f;
did = (lo >> 6) & 7;
if (boot_cpu_data.x86 == 0x10)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 53502d1bbf26..c88be6c37c30 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1346,7 +1346,7 @@ static void acpi_device_set_id(struct acpi_device *device)
acpi_add_id(device, ACPI_DOCK_HID);
else if (!acpi_ibm_smbus_match(device))
acpi_add_id(device, ACPI_SMBUS_IBM_HID);
- else if (!acpi_device_hid(device) &&
+ else if (list_empty(&device->pnp.ids) &&
ACPI_IS_ROOT_DEVICE(device->parent)) {
acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);