Merge tag 'pm+acpi-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
"These include a fix for a recent ACPI regression related to device
notifications, intel_idle fix related to IvyTown support, fix for a
buffer size issue in ACPICA, PM core fix related to the "freeze" sleep
state, four fixes for various types of breakage in cpufreq drivers, a
PNP workaround for a wrong memory region size in ACPI tables, and a
fix and cleanup for the ACPI tools Makefile.
Specifics:
- Fix for broken ACPI notifications on some systems caused by a
recent ACPI hotplug commit that blocked the propagation of unknown
type notifications to device drivers inadvertently.
- intel_idle fix to make the IvyTown C-states handling (added
recently) work as intended which now is broken due to missing
braces. From Christoph Jaeger.
- ACPICA fix to make it allocate buffers of the right sizes for the
Generic Serial Bus operation region access. From Lv Zheng.
- PM core fix unblocking cpuidle before entering the "freeze" sleep
state which causes that state to be able to actually save more
energy than runtime idle.
- Configuration and build fixes for the highbank and powernv cpufreq
drivers from Kefeng Wang and Srivatsa S Bhat.
- Coccinelle warning fix related to error pointers for the unicore32
cpufreq driver from Duan Jiong.
- Integer overflow fix for the ppc-corenet cpufreq driver from Geert
Uytterhoeven.
- Workaround for BIOSes that don't report the entire Intel MCH area
in their ACPI tables from Bjorn Helgaas.
- ACPI tools Makefile fix and cleanup from Thomas Renninger"
* tag 'pm+acpi-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI / notify: Do not block unknown type notifications in root handler
PNP: Work around BIOS defects in Intel MCH area reporting
cpufreq: highbank: fix ARM_HIGHBANK_CPUFREQ dependency warning
cpufreq: ppc: Fix integer overflow in expression
cpufreq, powernv: Fix build failure on UP
cpufreq: unicore32: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
PM / suspend: Make cpuidle work in the "freeze" state
intel_idle: fix IVT idle state table setting
ACPICA: Fix buffer allocation issue for generic_serial_bus region accesses.
tools/power/acpi: Minor bugfixes
This commit is contained in:
@@ -45,10 +45,71 @@
|
||||
#include "accommon.h"
|
||||
#include "acdispat.h"
|
||||
#include "acinterp.h"
|
||||
#include "amlcode.h"
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exfield")
|
||||
|
||||
/* Local prototypes */
|
||||
static u32
|
||||
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_get_serial_access_bytes
|
||||
*
|
||||
* PARAMETERS: accessor_type - The type of the protocol indicated by region
|
||||
* field access attributes
|
||||
* access_length - The access length of the region field
|
||||
*
|
||||
* RETURN: Decoded access length
|
||||
*
|
||||
* DESCRIPTION: This routine returns the length of the generic_serial_bus
|
||||
* protocol bytes
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u32
|
||||
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
|
||||
{
|
||||
u32 length;
|
||||
|
||||
switch (accessor_type) {
|
||||
case AML_FIELD_ATTRIB_QUICK:
|
||||
|
||||
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 = access_length;
|
||||
break;
|
||||
|
||||
case AML_FIELD_ATTRIB_BLOCK:
|
||||
case AML_FIELD_ATTRIB_BLOCK_CALL:
|
||||
default:
|
||||
|
||||
length = ACPI_GSBUS_BUFFER_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
return (length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_read_data_from_field
|
||||
@@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield")
|
||||
* Buffer, depending on the size of the field.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
||||
acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **ret_buffer_desc)
|
||||
{
|
||||
@@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
||||
acpi_size length;
|
||||
void *buffer;
|
||||
u32 function;
|
||||
u16 accessor_type;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
|
||||
|
||||
@@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
||||
ACPI_READ | (obj_desc->field.attribute << 16);
|
||||
} else if (obj_desc->field.region_obj->region.space_id ==
|
||||
ACPI_ADR_SPACE_GSBUS) {
|
||||
length = ACPI_GSBUS_BUFFER_SIZE;
|
||||
function =
|
||||
ACPI_READ | (obj_desc->field.attribute << 16);
|
||||
accessor_type = obj_desc->field.attribute;
|
||||
length = acpi_ex_get_serial_access_length(accessor_type,
|
||||
obj_desc->
|
||||
field.
|
||||
access_length);
|
||||
|
||||
/*
|
||||
* Add additional 2 bytes for modeled generic_serial_bus data buffer:
|
||||
* typedef struct {
|
||||
* BYTEStatus; // Byte 0 of the data buffer
|
||||
* BYTELength; // Byte 1 of the data buffer
|
||||
* BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
|
||||
* }
|
||||
*/
|
||||
length += 2;
|
||||
function = ACPI_READ | (accessor_type << 16);
|
||||
} else { /* IPMI */
|
||||
|
||||
length = ACPI_IPMI_BUFFER_SIZE;
|
||||
@@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
||||
void *buffer;
|
||||
union acpi_operand_object *buffer_desc;
|
||||
u32 function;
|
||||
u16 accessor_type;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
|
||||
|
||||
@@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
||||
ACPI_WRITE | (obj_desc->field.attribute << 16);
|
||||
} else if (obj_desc->field.region_obj->region.space_id ==
|
||||
ACPI_ADR_SPACE_GSBUS) {
|
||||
length = ACPI_GSBUS_BUFFER_SIZE;
|
||||
function =
|
||||
ACPI_WRITE | (obj_desc->field.attribute << 16);
|
||||
accessor_type = obj_desc->field.attribute;
|
||||
length = acpi_ex_get_serial_access_length(accessor_type,
|
||||
obj_desc->
|
||||
field.
|
||||
access_length);
|
||||
|
||||
/*
|
||||
* Add additional 2 bytes for modeled generic_serial_bus data buffer:
|
||||
* typedef struct {
|
||||
* BYTEStatus; // Byte 0 of the data buffer
|
||||
* BYTELength; // Byte 1 of the data buffer
|
||||
* BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
|
||||
* }
|
||||
*/
|
||||
length += 2;
|
||||
function = ACPI_WRITE | (accessor_type << 16);
|
||||
} else { /* IPMI */
|
||||
|
||||
length = ACPI_IPMI_BUFFER_SIZE;
|
||||
|
||||
@@ -380,9 +380,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
|
||||
break;
|
||||
|
||||
default:
|
||||
acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
|
||||
ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
|
||||
goto err;
|
||||
acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
adev = acpi_bus_get_acpi_device(handle);
|
||||
|
||||
@@ -92,11 +92,7 @@ config ARM_EXYNOS_CPU_FREQ_BOOST_SW
|
||||
|
||||
config ARM_HIGHBANK_CPUFREQ
|
||||
tristate "Calxeda Highbank-based"
|
||||
depends on ARCH_HIGHBANK
|
||||
select GENERIC_CPUFREQ_CPU0
|
||||
select PM_OPP
|
||||
select REGULATOR
|
||||
|
||||
depends on ARCH_HIGHBANK && GENERIC_CPUFREQ_CPU0 && REGULATOR
|
||||
default m
|
||||
help
|
||||
This adds the CPUFreq driver for Calxeda Highbank SoC
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <asm/cputhreads.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */
|
||||
|
||||
#define POWERNV_MAX_PSTATES 256
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
per_cpu(cpu_data, i) = data;
|
||||
|
||||
policy->cpuinfo.transition_latency =
|
||||
(12 * NSEC_PER_SEC) / fsl_get_sys_freq();
|
||||
(12ULL * NSEC_PER_SEC) / fsl_get_sys_freq();
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -60,9 +60,7 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
|
||||
policy->max = policy->cpuinfo.max_freq = 1000000;
|
||||
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
|
||||
policy->clk = clk_get(NULL, "MAIN_CLK");
|
||||
if (IS_ERR(policy->clk))
|
||||
return PTR_ERR(policy->clk);
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(policy->clk);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver ucv2_driver = {
|
||||
|
||||
@@ -750,9 +750,10 @@ void intel_idle_state_table_update(void)
|
||||
if (package_num + 1 > num_sockets) {
|
||||
num_sockets = package_num + 1;
|
||||
|
||||
if (num_sockets > 4)
|
||||
if (num_sockets > 4) {
|
||||
cpuidle_state_table = ivt_cstates_8s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pnp.h>
|
||||
@@ -334,6 +335,81 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/* Device IDs of parts that have 32KB MCH space */
|
||||
static const unsigned int mch_quirk_devices[] = {
|
||||
0x0154, /* Ivy Bridge */
|
||||
0x0c00, /* Haswell */
|
||||
};
|
||||
|
||||
static struct pci_dev *get_intel_host(void)
|
||||
{
|
||||
int i;
|
||||
struct pci_dev *host;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {
|
||||
host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],
|
||||
NULL);
|
||||
if (host)
|
||||
return host;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void quirk_intel_mch(struct pnp_dev *dev)
|
||||
{
|
||||
struct pci_dev *host;
|
||||
u32 addr_lo, addr_hi;
|
||||
struct pci_bus_region region;
|
||||
struct resource mch;
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
|
||||
host = get_intel_host();
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
/*
|
||||
* MCHBAR is not an architected PCI BAR, so MCH space is usually
|
||||
* reported as a PNP0C02 resource. The MCH space was originally
|
||||
* 16KB, but is 32KB in newer parts. Some BIOSes still report a
|
||||
* PNP0C02 resource that is only 16KB, which means the rest of the
|
||||
* MCH space is consumed but unreported.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read MCHBAR for Host Member Mapped Register Range Base
|
||||
* https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet
|
||||
* Sec 3.1.12.
|
||||
*/
|
||||
pci_read_config_dword(host, 0x48, &addr_lo);
|
||||
region.start = addr_lo & ~0x7fff;
|
||||
pci_read_config_dword(host, 0x4c, &addr_hi);
|
||||
region.start |= (u64) addr_hi << 32;
|
||||
region.end = region.start + 32*1024 - 1;
|
||||
|
||||
memset(&mch, 0, sizeof(mch));
|
||||
mch.flags = IORESOURCE_MEM;
|
||||
pcibios_bus_to_resource(host->bus, &mch, ®ion);
|
||||
|
||||
list_for_each_entry(pnp_res, &dev->resources, list) {
|
||||
res = &pnp_res->res;
|
||||
if (res->end < mch.start || res->start > mch.end)
|
||||
continue; /* no overlap */
|
||||
if (res->start == mch.start && res->end == mch.end)
|
||||
continue; /* exact match */
|
||||
|
||||
dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",
|
||||
res, pci_name(host), &mch);
|
||||
res->start = mch.start;
|
||||
res->end = mch.end;
|
||||
break;
|
||||
}
|
||||
|
||||
pci_dev_put(host);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PnP Quirks
|
||||
* Cards or devices that need some tweaking due to incomplete resource info
|
||||
@@ -363,6 +439,9 @@ static struct pnp_fixup pnp_fixups[] = {
|
||||
{"PNP0c02", quirk_system_pci_resources},
|
||||
#ifdef CONFIG_AMD_NB
|
||||
{"PNP0c01", quirk_amd_mmconfig_area},
|
||||
#endif
|
||||
#ifdef CONFIG_X86
|
||||
{"PNP0c02", quirk_intel_mch},
|
||||
#endif
|
||||
{""}
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/io.h>
|
||||
@@ -53,7 +54,9 @@ static void freeze_begin(void)
|
||||
|
||||
static void freeze_enter(void)
|
||||
{
|
||||
cpuidle_resume();
|
||||
wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
|
||||
cpuidle_pause();
|
||||
}
|
||||
|
||||
void freeze_wake(void)
|
||||
|
||||
@@ -89,15 +89,6 @@ else
|
||||
STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
|
||||
endif
|
||||
|
||||
# if DEBUG is enabled, then we do not strip or optimize
|
||||
ifeq ($(strip $(DEBUG)),true)
|
||||
CFLAGS += -O1 -g -DDEBUG
|
||||
STRIPCMD = /bin/true -Since_we_are_debugging
|
||||
else
|
||||
CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
|
||||
STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
|
||||
endif
|
||||
|
||||
# --- ACPIDUMP BEGIN ---
|
||||
|
||||
vpath %.c \
|
||||
@@ -128,7 +119,7 @@ clean:
|
||||
-rm -f $(OUTPUT)acpidump
|
||||
|
||||
install-tools:
|
||||
$(INSTALL) -d $(DESTDIR)${bindir}
|
||||
$(INSTALL) -d $(DESTDIR)${sbindir}
|
||||
$(INSTALL_PROGRAM) $(OUTPUT)acpidump $(DESTDIR)${sbindir}
|
||||
|
||||
install-man:
|
||||
|
||||
Reference in New Issue
Block a user