summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-24 15:51:02 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-24 15:51:02 -0800
commit09da8dfa98682d871987145ed11e3232accac860 (patch)
tree152a9bb1e52f70db6efb66fffbdc4871f749d7df /drivers/acpi
parent3aacd625f20129f5a41ea3ff3b5353b0e4dabd01 (diff)
parent7744064731a9543105e207504e0262f883bc14c0 (diff)
downloadblackbird-op-linux-09da8dfa98682d871987145ed11e3232accac860.tar.gz
blackbird-op-linux-09da8dfa98682d871987145ed11e3232accac860.zip
Merge tag 'pm+acpi-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management updates from Rafael Wysocki: "As far as the number of commits goes, the top spot belongs to ACPI this time with cpufreq in the second position and a handful of PM core, PNP and cpuidle updates. They are fixes and cleanups mostly, as usual, with a couple of new features in the mix. The most visible change is probably that we will create struct acpi_device objects (visible in sysfs) for all devices represented in the ACPI tables regardless of their status and there will be a new sysfs attribute under those objects allowing user space to check that status via _STA. Consequently, ACPI device eject or generally hot-removal will not delete those objects, unless the table containing the corresponding namespace nodes is unloaded, which is extremely rare. Also ACPI container hotplug will be handled quite a bit differently and cpufreq will support CPU boost ("turbo") generically and not only in the acpi-cpufreq driver. Specifics: - ACPI core changes to make it create a struct acpi_device object for every device represented in the ACPI tables during all namespace scans regardless of the current status of that device. In accordance with this, ACPI hotplug operations will not delete those objects, unless the underlying ACPI tables go away. - On top of the above, new sysfs attribute for ACPI device objects allowing user space to check device status by triggering the execution of _STA for its ACPI object. From Srinivas Pandruvada. - ACPI core hotplug changes reducing code duplication, integrating the PCI root hotplug with the core and reworking container hotplug. - ACPI core simplifications making it use ACPI_COMPANION() in the code "glueing" ACPI device objects to "physical" devices. - ACPICA update to upstream version 20131218. This adds support for the DBG2 and PCCT tables to ACPICA, fixes some bugs and improves debug facilities. From Bob Moore, Lv Zheng and Betty Dall. - Init code change to carry out the early ACPI initialization earlier. That should allow us to use ACPI during the timekeeping initialization and possibly to simplify the EFI initialization too. From Chun-Yi Lee. - Clenups of the inclusions of ACPI headers in many places all over from Lv Zheng and Rashika Kheria (work in progress). - New helper for ACPI _DSM execution and rework of the code in drivers that uses _DSM to execute it via the new helper. From Jiang Liu. - New Win8 OSI blacklist entries from Takashi Iwai. - Assorted ACPI fixes and cleanups from Al Stone, Emil Goode, Hanjun Guo, Lan Tianyu, Masanari Iida, Oliver Neukum, Prarit Bhargava, Rashika Kheria, Tang Chen, Zhang Rui. - intel_pstate driver updates, including proper Baytrail support, from Dirk Brandewie and intel_pstate documentation from Ramkumar Ramachandra. - Generic CPU boost ("turbo") support for cpufreq from Lukasz Majewski. - powernow-k6 cpufreq driver fixes from Mikulas Patocka. - cpufreq core fixes and cleanups from Viresh Kumar, Jane Li, Mark Brown. - Assorted cpufreq drivers fixes and cleanups from Anson Huang, John Tobias, Paul Bolle, Paul Walmsley, Sachin Kamat, Shawn Guo, Viresh Kumar. - cpuidle cleanups from Bartlomiej Zolnierkiewicz. - Support for hibernation APM events from Bin Shi. - Hibernation fix to avoid bringing up nonboot CPUs with ACPI EC disabled during thaw transitions from Bjørn Mork. - PM core fixes and cleanups from Ben Dooks, Leonardo Potenza, Ulf Hansson. - PNP subsystem fixes and cleanups from Dmitry Torokhov, Levente Kurusa, Rashika Kheria. - New tool for profiling system suspend from Todd E Brandt and a cpupower tool cleanup from One Thousand Gnomes" * tag 'pm+acpi-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (153 commits) thermal: exynos: boost: Automatic enable/disable of BOOST feature (at Exynos4412) cpufreq: exynos4x12: Change L0 driver data to CPUFREQ_BOOST_FREQ Documentation: cpufreq / boost: Update BOOST documentation cpufreq: exynos: Extend Exynos cpufreq driver to support boost cpufreq / boost: Kconfig: Support for software-managed BOOST acpi-cpufreq: Adjust the code to use the common boost attribute cpufreq: Add boost frequency support in core intel_pstate: Add trace point to report internal state. cpufreq: introduce cpufreq_generic_get() routine ARM: SA1100: Create dummy clk_get_rate() to avoid build failures cpufreq: stats: create sysfs entries when cpufreq_stats is a module cpufreq: stats: free table and remove sysfs entry in a single routine cpufreq: stats: remove hotplug notifiers cpufreq: stats: handle cpufreq_unregister_driver() and suspend/resume properly cpufreq: speedstep: remove unused speedstep_get_state platform: introduce OF style 'modalias' support for platform bus PM / tools: new tool for suspend/resume performance optimization ACPI: fix module autoloading for ACPI enumerated devices ACPI: add module autoloading support for ACPI enumerated devices ACPI: fix create_modalias() return value handling ...
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/ac.c3
-rw-r--r--drivers/acpi/acpi_extlog.c62
-rw-r--r--drivers/acpi/acpi_memhotplug.c27
-rw-r--r--drivers/acpi/acpi_pad.c3
-rw-r--r--drivers/acpi/acpi_processor.c26
-rw-r--r--drivers/acpi/acpica/acdebug.h1
-rw-r--r--drivers/acpi/acpica/acevents.h9
-rw-r--r--drivers/acpi/acpica/acglobal.h30
-rw-r--r--drivers/acpi/acpica/aclocal.h9
-rw-r--r--drivers/acpi/acpica/dsfield.c2
-rw-r--r--drivers/acpi/acpica/dsutils.c19
-rw-r--r--drivers/acpi/acpica/dswload.c4
-rw-r--r--drivers/acpi/acpica/evgpeblk.c8
-rw-r--r--drivers/acpi/acpica/evgpeutil.c24
-rw-r--r--drivers/acpi/acpica/exresnte.c3
-rw-r--r--drivers/acpi/acpica/nsxfeval.c23
-rw-r--r--drivers/acpi/acpica/psopinfo.c51
-rw-r--r--drivers/acpi/acpica/tbfadt.c335
-rw-r--r--drivers/acpi/acpica/tbutils.c214
-rw-r--r--drivers/acpi/acpica/utaddress.c19
-rw-r--r--drivers/acpi/acpica/utalloc.c10
-rw-r--r--drivers/acpi/acpica/utcache.c12
-rw-r--r--drivers/acpi/acpica/utdebug.c4
-rw-r--r--drivers/acpi/acpica/utglobal.c4
-rw-r--r--drivers/acpi/acpica/utxfinit.c12
-rw-r--r--drivers/acpi/apei/apei-base.c1
-rw-r--r--drivers/acpi/apei/apei-internal.h1
-rw-r--r--drivers/acpi/apei/einj.c1
-rw-r--r--drivers/acpi/apei/ghes.c1
-rw-r--r--drivers/acpi/battery.c3
-rw-r--r--drivers/acpi/blacklist.c51
-rw-r--r--drivers/acpi/bus.c77
-rw-r--r--drivers/acpi/button.c21
-rw-r--r--drivers/acpi/container.c55
-rw-r--r--drivers/acpi/custom_method.c2
-rw-r--r--drivers/acpi/debugfs.c2
-rw-r--r--drivers/acpi/device_pm.c22
-rw-r--r--drivers/acpi/dock.c16
-rw-r--r--drivers/acpi/ec.c32
-rw-r--r--drivers/acpi/ec_sys.c2
-rw-r--r--drivers/acpi/event.c2
-rw-r--r--drivers/acpi/fan.c3
-rw-r--r--drivers/acpi/glue.c165
-rw-r--r--drivers/acpi/hed.c2
-rw-r--r--drivers/acpi/internal.h19
-rw-r--r--drivers/acpi/numa.c1
-rw-r--r--drivers/acpi/nvs.c3
-rw-r--r--drivers/acpi/osl.c14
-rw-r--r--drivers/acpi/pci_irq.c2
-rw-r--r--drivers/acpi/pci_link.c4
-rw-r--r--drivers/acpi/pci_root.c126
-rw-r--r--drivers/acpi/pci_slot.c1
-rw-r--r--drivers/acpi/power.c3
-rw-r--r--drivers/acpi/proc.c5
-rw-r--r--drivers/acpi/processor_core.c3
-rw-r--r--drivers/acpi/processor_driver.c8
-rw-r--r--drivers/acpi/processor_idle.c37
-rw-r--r--drivers/acpi/processor_perflib.c7
-rw-r--r--drivers/acpi/processor_thermal.c11
-rw-r--r--drivers/acpi/processor_throttling.c7
-rw-r--r--drivers/acpi/sbshc.c3
-rw-r--r--drivers/acpi/scan.c620
-rw-r--r--drivers/acpi/sleep.c14
-rw-r--r--drivers/acpi/sysfs.c2
-rw-r--r--drivers/acpi/tables.c11
-rw-r--r--drivers/acpi/thermal.c7
-rw-r--r--drivers/acpi/utils.c99
-rw-r--r--drivers/acpi/video.c5
-rw-r--r--drivers/acpi/video_detect.c2
-rw-r--r--drivers/acpi/wakeup.c1
70 files changed, 1295 insertions, 1093 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 3c2e4aa529c4..e7515aa43d6b 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -32,8 +32,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 5d33c5415405..c4a5d87ede7e 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
#include <linux/cper.h>
#include <linux/ratelimit.h>
#include <linux/edac.h>
@@ -21,11 +20,9 @@
#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */
#define EXTLOG_DSM_REV 0x0
-#define EXTLOG_FN_QUERY 0x0
#define EXTLOG_FN_ADDR 0x1
#define FLAG_OS_OPTIN BIT(0)
-#define EXTLOG_QUERY_L1_EXIST BIT(1)
#define ELOG_ENTRY_VALID (1ULL<<63)
#define ELOG_ENTRY_LEN 0x1000
@@ -46,7 +43,7 @@ struct extlog_l1_head {
static int old_edac_report_status;
-static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295";
+static u8 extlog_dsm_uuid[] __initdata = "663E35AF-CC10-41A4-88EA-5470AF055295";
/* L1 table related physical address */
static u64 elog_base;
@@ -156,62 +153,27 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
return NOTIFY_STOP;
}
-static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret)
+static bool __init extlog_get_l1addr(void)
{
- struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_object_list input;
- union acpi_object params[4], *obj;
u8 uuid[16];
- int i;
+ acpi_handle handle;
+ union acpi_object *obj;
acpi_str_to_uuid(extlog_dsm_uuid, uuid);
- input.count = 4;
- input.pointer = params;
- params[0].type = ACPI_TYPE_BUFFER;
- params[0].buffer.length = 16;
- params[0].buffer.pointer = uuid;
- params[1].type = ACPI_TYPE_INTEGER;
- params[1].integer.value = rev;
- params[2].type = ACPI_TYPE_INTEGER;
- params[2].integer.value = func;
- params[3].type = ACPI_TYPE_PACKAGE;
- params[3].package.count = 0;
- params[3].package.elements = NULL;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf)))
- return -1;
-
- *ret = 0;
- obj = (union acpi_object *)buf.pointer;
- if (obj->type == ACPI_TYPE_INTEGER) {
- *ret = obj->integer.value;
- } else if (obj->type == ACPI_TYPE_BUFFER) {
- if (obj->buffer.length <= 8) {
- for (i = 0; i < obj->buffer.length; i++)
- *ret |= (obj->buffer.pointer[i] << (i * 8));
- }
- }
- kfree(buf.pointer);
-
- return 0;
-}
-
-static bool extlog_get_l1addr(void)
-{
- acpi_handle handle;
- u64 ret;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return false;
-
- if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_QUERY, &ret) ||
- !(ret & EXTLOG_QUERY_L1_EXIST))
+ if (!acpi_check_dsm(handle, uuid, EXTLOG_DSM_REV, 1 << EXTLOG_FN_ADDR))
return false;
-
- if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_ADDR, &ret))
+ obj = acpi_evaluate_dsm_typed(handle, uuid, EXTLOG_DSM_REV,
+ EXTLOG_FN_ADDR, NULL, ACPI_TYPE_INTEGER);
+ if (!obj) {
return false;
+ } else {
+ l1_dirbase = obj->integer.value;
+ ACPI_FREE(obj);
+ }
- l1_dirbase = ret;
/* Spec says L1 directory must be 4K aligned, bail out if it isn't */
if (l1_dirbase & ((1 << 12) - 1)) {
pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n",
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 551dad712ffe..b67be85ff0fc 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -180,14 +180,14 @@ static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info)
static int acpi_bind_memblk(struct memory_block *mem, void *arg)
{
- return acpi_bind_one(&mem->dev, (acpi_handle)arg);
+ return acpi_bind_one(&mem->dev, arg);
}
static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
- acpi_handle handle)
+ struct acpi_device *adev)
{
return walk_memory_range(acpi_meminfo_start_pfn(info),
- acpi_meminfo_end_pfn(info), (void *)handle,
+ acpi_meminfo_end_pfn(info), adev,
acpi_bind_memblk);
}
@@ -197,8 +197,7 @@ static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
return 0;
}
-static void acpi_unbind_memory_blocks(struct acpi_memory_info *info,
- acpi_handle handle)
+static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
{
walk_memory_range(acpi_meminfo_start_pfn(info),
acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk);
@@ -242,9 +241,9 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
if (result && result != -EEXIST)
continue;
- result = acpi_bind_memory_blocks(info, handle);
+ result = acpi_bind_memory_blocks(info, mem_device->device);
if (result) {
- acpi_unbind_memory_blocks(info, handle);
+ acpi_unbind_memory_blocks(info);
return -ENODEV;
}
@@ -285,7 +284,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
if (nid == NUMA_NO_NODE)
nid = memory_add_physaddr_to_nid(info->start_addr);
- acpi_unbind_memory_blocks(info, handle);
+ acpi_unbind_memory_blocks(info);
remove_memory(nid, info->start_addr, info->length);
list_del(&info->list);
kfree(info);
@@ -361,7 +360,19 @@ static void acpi_memory_device_remove(struct acpi_device *device)
acpi_memory_device_free(mem_device);
}
+static bool __initdata acpi_no_memhotplug;
+
void __init acpi_memory_hotplug_init(void)
{
+ if (acpi_no_memhotplug)
+ return;
+
acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
}
+
+static int __init disable_acpi_memory_hotplug(char *str)
+{
+ acpi_no_memhotplug = true;
+ return 1;
+}
+__setup("acpi_no_memhotplug", disable_acpi_memory_hotplug);
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 509452a62f96..df96a0fe4890 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -28,8 +28,7 @@
#include <linux/cpu.h>
#include <linux/clockchips.h>
#include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <asm/mwait.h>
#define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad"
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 3c1d6b0c09a4..c9311be29a64 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -212,7 +212,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
union acpi_object object = { 0 };
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
struct acpi_processor *pr = acpi_driver_data(device);
- int cpu_index, device_declaration = 0;
+ int apic_id, cpu_index, device_declaration = 0;
acpi_status status = AE_OK;
static int cpu0_initialized;
unsigned long long value;
@@ -258,18 +258,21 @@ static int acpi_processor_get_info(struct acpi_device *device)
device_declaration = 1;
pr->acpi_id = value;
}
- pr->apic_id = acpi_get_apicid(pr->handle, device_declaration,
- pr->acpi_id);
- cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
- /* Handle UP system running SMP kernel, with no LAPIC in MADT */
- if (!cpu0_initialized && (cpu_index == -1) &&
- (num_online_cpus() == 1)) {
- cpu_index = 0;
+ apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id);
+ if (apic_id < 0) {
+ acpi_handle_err(pr->handle, "failed to get CPU APIC ID.\n");
+ return -ENODEV;
}
+ pr->apic_id = apic_id;
- cpu0_initialized = 1;
-
+ cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
+ if (!cpu0_initialized) {
+ cpu0_initialized = 1;
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if ((cpu_index == -1) && (num_online_cpus() == 1))
+ cpu_index = 0;
+ }
pr->id = cpu_index;
/*
@@ -282,6 +285,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
if (ret)
return ret;
}
+
/*
* On some boxes several processors use the same processor bus id.
* But they are located in different scope. For example:
@@ -395,7 +399,7 @@ static int acpi_processor_add(struct acpi_device *device,
goto err;
}
- result = acpi_bind_one(dev, pr->handle);
+ result = acpi_bind_one(dev, device);
if (result)
goto err;
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index a9fd0b872062..2bf3ca2b8a7a 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -113,7 +113,6 @@ void acpi_db_display_handlers(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_db_generate_gpe(char *gpe_arg,
char *block_arg))
-
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
/*
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 41abe552c7a3..0fb0adf435d6 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -71,9 +71,8 @@ acpi_status acpi_ev_init_global_lock_handler(void);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
acpi_ev_acquire_global_lock(u16 timeout))
-
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
- acpi_status acpi_ev_remove_global_lock_handler(void);
+acpi_status acpi_ev_remove_global_lock_handler(void);
/*
* evgpe - Low-level GPE support
@@ -133,7 +132,7 @@ acpi_status acpi_ev_gpe_initialize(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_ev_update_gpes(acpi_owner_id table_owner_id))
- acpi_status
+acpi_status
acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@@ -149,7 +148,9 @@ acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context);
-struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number);
+acpi_status
+acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
+ struct acpi_gpe_xrupt_info **gpe_xrupt_block);
acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index e9f1fc7f99c7..24db8e153bf0 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -119,6 +119,24 @@ bool ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
/*
+ * Optionally ignore an XSDT if present and use the RSDT instead.
+ * Although the ACPI specification requires that an XSDT be used instead
+ * of the RSDT, the XSDT has been found to be corrupt or ill-formed on
+ * some machines. Default behavior is to use the XSDT if present.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_do_not_use_xsdt, FALSE);
+
+/*
+ * Optionally use 32-bit FADT addresses if and when there is a conflict
+ * (address mismatch) between the 32-bit and 64-bit versions of the
+ * address. Although ACPICA adheres to the ACPI specification which
+ * requires the use of the corresponding 64-bit address if it is non-zero,
+ * some machines have been found to have a corrupted non-zero 64-bit
+ * address. Default is FALSE, do not favor the 32-bit addresses.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_use32_bit_fadt_addresses, FALSE);
+
+/*
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
* with other ACPI implementations. NOTE: During ACPICA initialization,
* this value is set to TRUE if any Windows OSI strings have been
@@ -484,6 +502,18 @@ ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects;
/*****************************************************************************
*
+ * Application globals
+ *
+ ****************************************************************************/
+
+#ifdef ACPI_APPLICATION
+
+ACPI_FILE ACPI_INIT_GLOBAL(acpi_gbl_debug_file, NULL);
+
+#endif /* ACPI_APPLICATION */
+
+/*****************************************************************************
+ *
* Info/help support
*
****************************************************************************/
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 53ed1a8ba4f0..d95ca5449ace 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -1038,15 +1038,16 @@ struct acpi_external_list {
struct acpi_external_list *next;
u32 value;
u16 length;
+ u16 flags;
u8 type;
- u8 flags;
- u8 resolved;
- u8 emitted;
};
/* Values for Flags field above */
-#define ACPI_IPATH_ALLOCATED 0x01
+#define ACPI_EXT_RESOLVED_REFERENCE 0x01 /* Object was resolved during cross ref */
+#define ACPI_EXT_ORIGIN_FROM_FILE 0x02 /* External came from a file */
+#define ACPI_EXT_INTERNAL_PATH_ALLOCATED 0x04 /* Deallocate internal path on completion */
+#define ACPI_EXT_EXTERNAL_EMITTED 0x08 /* External() statement has been emitted */
struct acpi_external_file {
char *path;
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 2d4c07322576..e7a57c554e84 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -105,7 +105,7 @@ acpi_ds_create_external_region(acpi_status lookup_status,
* operation_region not found. Generate an External for it, and
* insert the name into the namespace.
*/
- acpi_dm_add_to_external_list(op, path, ACPI_TYPE_REGION, 0);
+ acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
walk_state, node);
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index ade44e49deb4..d7f53fb2979a 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -727,27 +727,26 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
index++;
}
- index--;
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "NumOperands %d, ArgCount %d, Index %d\n",
+ walk_state->num_operands, arg_count, index));
- /* It is the appropriate order to get objects from the Result stack */
+ /* Create the interpreter arguments, in reverse order */
+ index--;
for (i = 0; i < arg_count; i++) {
arg = arguments[index];
-
- /* Force the filling of the operand stack in inverse order */
-
- walk_state->operand_index = (u8) index;
+ walk_state->operand_index = (u8)index;
status = acpi_ds_create_operand(walk_state, arg, index);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
- index--;
-
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "Arg #%u (%p) done, Arg1=%p\n", index, arg,
- first_arg));
+ "Created Arg #%u (%p) %u args total\n",
+ index, arg, arg_count));
+ index--;
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 95e681a36f9c..2dbe109727c8 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -181,8 +181,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
* Target of Scope() not found. Generate an External for it, and
* insert the name into the namespace.
*/
- acpi_dm_add_to_external_list(op, path, ACPI_TYPE_DEVICE,
- 0);
+ acpi_dm_add_op_to_external_list(op, path,
+ ACPI_TYPE_DEVICE, 0, 0);
status =
acpi_ns_lookup(walk_state->scope_info, path,
object_type, ACPI_IMODE_LOAD_PASS1,
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index a9e76bc4ad97..a31e549e64cc 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -87,9 +87,9 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
return_ACPI_STATUS(status);
}
- gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number);
- if (!gpe_xrupt_block) {
- status = AE_NO_MEMORY;
+ status =
+ acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -112,7 +112,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
unlock_and_exit:
- status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index d3f5e1e2a2b1..4d764e847a08 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -197,8 +197,9 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
* PARAMETERS: interrupt_number - Interrupt for a GPE block
+ * gpe_xrupt_block - Where the block is returned
*
- * RETURN: A GPE interrupt block
+ * RETURN: Status
*
* DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
* block per unique interrupt level used for GPEs. Should be
@@ -207,7 +208,9 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
*
******************************************************************************/
-struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number)
+acpi_status
+acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
+ struct acpi_gpe_xrupt_info ** gpe_xrupt_block)
{
struct acpi_gpe_xrupt_info *next_gpe_xrupt;
struct acpi_gpe_xrupt_info *gpe_xrupt;
@@ -221,7 +224,8 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number)
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt) {
if (next_gpe_xrupt->interrupt_number == interrupt_number) {
- return_PTR(next_gpe_xrupt);
+ *gpe_xrupt_block = next_gpe_xrupt;
+ return_ACPI_STATUS(AE_OK);
}
next_gpe_xrupt = next_gpe_xrupt->next;
@@ -231,7 +235,7 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number)
gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
- return_PTR(NULL);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
gpe_xrupt->interrupt_number = interrupt_number;
@@ -250,6 +254,7 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number)
} else {
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
}
+
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Install new interrupt handler if not SCI_INT */
@@ -259,14 +264,15 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number)
acpi_ev_gpe_xrupt_handler,
gpe_xrupt);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO,
- "Could not install GPE interrupt handler at level 0x%X",
- interrupt_number));
- return_PTR(NULL);
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not install GPE interrupt handler at level 0x%X",
+ interrupt_number));
+ return_ACPI_STATUS(status);
}
}
- return_PTR(gpe_xrupt);
+ *gpe_xrupt_block = gpe_xrupt;
+ return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index acd34f599313..7ca6925a87ca 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -124,7 +124,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
}
if (!source_desc) {
- ACPI_ERROR((AE_INFO, "No object attached to node %p", node));
+ ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
+ node->name.ascii, node));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index e973e311f856..1f0c28ba50df 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -84,7 +84,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
acpi_object_type return_type)
{
acpi_status status;
- u8 must_free = FALSE;
+ u8 free_buffer_on_error = FALSE;
ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
@@ -95,14 +95,13 @@ acpi_evaluate_object_typed(acpi_handle handle,
}
if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
- must_free = TRUE;
+ free_buffer_on_error = TRUE;
}
/* Evaluate the object */
- status =
- acpi_evaluate_object(handle, pathname, external_params,
- return_buffer);
+ status = acpi_evaluate_object(handle, pathname,
+ external_params, return_buffer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -135,11 +134,15 @@ acpi_evaluate_object_typed(acpi_handle handle,
pointer)->type),
acpi_ut_get_type_name(return_type)));
- if (must_free) {
-
- /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
-
- ACPI_FREE_BUFFER(*return_buffer);
+ if (free_buffer_on_error) {
+ /*
+ * Free a buffer created via ACPI_ALLOCATE_BUFFER.
+ * Note: We use acpi_os_free here because acpi_os_allocate was used
+ * to allocate the buffer. This purposefully bypasses the
+ * (optionally enabled) allocation tracking mechanism since we
+ * only want to track internal allocations.
+ */
+ acpi_os_free(return_buffer->pointer);
return_buffer->pointer = NULL;
}
diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c
index 9ba5301e5751..b0c9787dbe61 100644
--- a/drivers/acpi/acpica/psopinfo.c
+++ b/drivers/acpi/acpica/psopinfo.c
@@ -71,6 +71,10 @@ static const u8 acpi_gbl_argument_count[] =
const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
{
+#ifdef ACPI_DEBUG_OUTPUT
+ const char *opcode_name = "Unknown AML opcode";
+#endif
+
ACPI_FUNCTION_NAME(ps_get_opcode_info);
/*
@@ -92,11 +96,54 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
return (&acpi_gbl_aml_op_info
[acpi_gbl_long_op_index[(u8)opcode]]);
}
+#if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT
+#include "asldefine.h"
+
+ switch (opcode) {
+ case AML_RAW_DATA_BYTE:
+ opcode_name = "-Raw Data Byte-";
+ break;
+
+ case AML_RAW_DATA_WORD:
+ opcode_name = "-Raw Data Word-";
+ break;
+
+ case AML_RAW_DATA_DWORD:
+ opcode_name = "-Raw Data Dword-";
+ break;
+
+ case AML_RAW_DATA_QWORD:
+ opcode_name = "-Raw Data Qword-";
+ break;
+
+ case AML_RAW_DATA_BUFFER:
+ opcode_name = "-Raw Data Buffer-";
+ break;
+
+ case AML_RAW_DATA_CHAIN:
+ opcode_name = "-Raw Data Buffer Chain-";
+ break;
+
+ case AML_PACKAGE_LENGTH:
+ opcode_name = "-Package Length-";
+ break;
+
+ case AML_UNASSIGNED_OPCODE:
+ opcode_name = "-Unassigned Opcode-";
+ break;
+
+ case AML_DEFAULT_ARG_OP:
+ opcode_name = "-Default Arg-";
+ break;
+
+ default:
+ break;
+ }
+#endif
/* Unknown AML opcode */
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Unknown AML opcode [%4.4X]\n", opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%4.4X]\n", opcode_name, opcode));
return (&acpi_gbl_aml_op_info[_UNK]);
}
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 9d99f2189693..8f89263ac47e 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -56,10 +56,11 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
static void acpi_tb_convert_fadt(void);
-static void acpi_tb_validate_fadt(void);
-
static void acpi_tb_setup_fadt_registers(void);
+static u64
+acpi_tb_select_address(char *register_name, u32 address32, u64 address64);
+
/* Table for conversion of FADT to common internal format and FADT validation */
typedef struct acpi_fadt_info {
@@ -175,6 +176,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
* space_id - ACPI Space ID for this register
* byte_width - Width of this register
* address - Address of the register
+ * register_name - ASCII name of the ACPI register
*
* RETURN: None
*
@@ -220,6 +222,68 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
/*******************************************************************************
*
+ * FUNCTION: acpi_tb_select_address
+ *
+ * PARAMETERS: register_name - ASCII name of the ACPI register
+ * address32 - 32-bit address of the register
+ * address64 - 64-bit address of the register
+ *
+ * RETURN: The resolved 64-bit address
+ *
+ * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within
+ * the FADT. Used for the FACS and DSDT addresses.
+ *
+ * NOTES:
+ *
+ * Check for FACS and DSDT address mismatches. An address mismatch between
+ * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
+ * DSDT/X_DSDT) could be a corrupted address field or it might indicate
+ * the presence of two FACS or two DSDT tables.
+ *
+ * November 2013:
+ * By default, as per the ACPICA specification, a valid 64-bit address is
+ * used regardless of the value of the 32-bit address. However, this
+ * behavior can be overridden via the acpi_gbl_use32_bit_fadt_addresses flag.
+ *
+ ******************************************************************************/
+
+static u64
+acpi_tb_select_address(char *register_name, u32 address32, u64 address64)
+{
+
+ if (!address64) {
+
+ /* 64-bit address is zero, use 32-bit address */
+
+ return ((u64)address32);
+ }
+
+ if (address32 && (address64 != (u64)address32)) {
+
+ /* Address mismatch between 32-bit and 64-bit versions */
+
+ ACPI_BIOS_WARNING((AE_INFO,
+ "32/64X %s address mismatch in FADT: "
+ "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
+ register_name, address32,
+ ACPI_FORMAT_UINT64(address64),
+ acpi_gbl_use32_bit_fadt_addresses ? 32 :
+ 64));
+
+ /* 32-bit address override */
+
+ if (acpi_gbl_use32_bit_fadt_addresses) {
+ return ((u64)address32);
+ }
+ }
+
+ /* Default is to use the 64-bit address */
+
+ return (address64);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_tb_parse_fadt
*
* PARAMETERS: table_index - Index for the FADT
@@ -331,10 +395,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
acpi_tb_convert_fadt();
- /* Validate FADT values now, before we make any changes */
-
- acpi_tb_validate_fadt();
-
/* Initialize the global ACPI register structures */
acpi_tb_setup_fadt_registers();
@@ -344,66 +404,55 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
*
* FUNCTION: acpi_tb_convert_fadt
*
- * PARAMETERS: None, uses acpi_gbl_FADT
+ * PARAMETERS: none - acpi_gbl_FADT is used.
*
* RETURN: None
*
* DESCRIPTION: Converts all versions of the FADT to a common internal format.
- * Expand 32-bit addresses to 64-bit as necessary.
+ * Expand 32-bit addresses to 64-bit as necessary. Also validate
+ * important fields within the FADT.
*
- * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt),
- * and must contain a copy of the actual FADT.
+ * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), and must
+ * contain a copy of the actual BIOS-provided FADT.
*
* Notes on 64-bit register addresses:
*
* After this FADT conversion, later ACPICA code will only use the 64-bit "X"
* fields of the FADT for all ACPI register addresses.
*
- * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
+ * The 64-bit X fields are optional extensions to the original 32-bit FADT
* V1.0 fields. Even if they are present in the FADT, they are optional and
* are unused if the BIOS sets them to zero. Therefore, we must copy/expand
- * 32-bit V1.0 fields if the corresponding X field is zero.
+ * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is
+ * originally zero.
*
- * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
- * corresponding "X" fields in the internal FADT.
+ * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address
+ * fields are expanded to the corresponding 64-bit X fields in the internal
+ * common FADT.
*
* For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
- * to the corresponding 64-bit X fields. For compatibility with other ACPI
- * implementations, we ignore the 64-bit field if the 32-bit field is valid,
- * regardless of whether the host OS is 32-bit or 64-bit.
+ * to the corresponding 64-bit X fields, if the 64-bit field is originally
+ * zero. Adhering to the ACPI specification, we completely ignore the 32-bit
+ * field if the 64-bit field is valid, regardless of whether the host OS is
+ * 32-bit or 64-bit.
+ *
+ * Possible additional checks:
+ * (acpi_gbl_FADT.pm1_event_length >= 4)
+ * (acpi_gbl_FADT.pm1_control_length >= 2)
+ * (acpi_gbl_FADT.pm_timer_length >= 4)
+ * Gpe block lengths must be multiple of 2
*
******************************************************************************/
static void acpi_tb_convert_fadt(void)
{
+ char *name;
struct acpi_generic_address *address64;
u32 address32;
+ u8 length;
u32 i;
/*
- * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
- * Later code will always use the X 64-bit field. Also, check for an
- * address mismatch between the 32-bit and 64-bit address fields
- * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate
- * the presence of two FACS or two DSDT tables.
- */
- if (!acpi_gbl_FADT.Xfacs) {
- acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
- } else if (acpi_gbl_FADT.facs &&
- (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
- ACPI_WARNING((AE_INFO,
- "32/64 FACS address mismatch in FADT - two FACS tables!"));
- }
-
- if (!acpi_gbl_FADT.Xdsdt) {
- acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
- } else if (acpi_gbl_FADT.dsdt &&
- (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
- ACPI_WARNING((AE_INFO,
- "32/64 DSDT address mismatch in FADT - two DSDT tables!"));
- }
-
- /*
* For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
* should be zero are indeed zero. This will workaround BIOSs that
* inadvertently place values in these fields.
@@ -421,119 +470,24 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.boot_flags = 0;
}
- /* Update the local FADT table header length */
-
- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
-
/*
- * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
- * generic address structures as necessary. Later code will always use
- * the 64-bit address structures.
- *
- * March 2009:
- * We now always use the 32-bit address if it is valid (non-null). This
- * is not in accordance with the ACPI specification which states that
- * the 64-bit address supersedes the 32-bit version, but we do this for
- * compatibility with other ACPI implementations. Most notably, in the
- * case where both the 32 and 64 versions are non-null, we use the 32-bit
- * version. This is the only address that is guaranteed to have been
- * tested by the BIOS manufacturer.
+ * Now we can update the local FADT length to the length of the
+ * current FADT version as defined by the ACPI specification.
+ * Thus, we will have a common FADT internally.
*/
- for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
- address32 = *ACPI_ADD_PTR(u32,
- &acpi_gbl_FADT,
- fadt_info_table[i].address32);
-
- address64 = ACPI_ADD_PTR(struct acpi_generic_address,
- &acpi_gbl_FADT,
- fadt_info_table[i].address64);
-
- /*
- * If both 32- and 64-bit addresses are valid (non-zero),
- * they must match.
- */
- if (address64->address && address32 &&
- (address64->address != (u64)address32)) {
- ACPI_BIOS_ERROR((AE_INFO,
- "32/64X address mismatch in FADT/%s: "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- fadt_info_table[i].name, address32,
- ACPI_FORMAT_UINT64(address64->
- address)));
- }
-
- /* Always use 32-bit address if it is valid (non-null) */
-
- if (address32) {
- /*
- * Copy the 32-bit address to the 64-bit GAS structure. The
- * Space ID is always I/O for 32-bit legacy address fields
- */
- acpi_tb_init_generic_address(address64,
- ACPI_ADR_SPACE_SYSTEM_IO,
- *ACPI_ADD_PTR(u8,
- &acpi_gbl_FADT,
- fadt_info_table
- [i].length),
- (u64) address32,
- fadt_info_table[i].name);
- }
- }
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_validate_fadt
- *
- * PARAMETERS: table - Pointer to the FADT to be validated
- *
- * RETURN: None
- *
- * DESCRIPTION: Validate various important fields within the FADT. If a problem
- * is found, issue a message, but no status is returned.
- * Used by both the table manager and the disassembler.
- *
- * Possible additional checks:
- * (acpi_gbl_FADT.pm1_event_length >= 4)
- * (acpi_gbl_FADT.pm1_control_length >= 2)
- * (acpi_gbl_FADT.pm_timer_length >= 4)
- * Gpe block lengths must be multiple of 2
- *
- ******************************************************************************/
-
-static void acpi_tb_validate_fadt(void)
-{
- char *name;
- struct acpi_generic_address *address64;
- u8 length;
- u32 i;
+ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
/*
- * Check for FACS and DSDT address mismatches. An address mismatch between
- * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
- * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
+ * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
+ * Later ACPICA code will always use the X 64-bit field.
*/
- if (acpi_gbl_FADT.facs &&
- (acpi_gbl_FADT.Xfacs != (u64)acpi_gbl_FADT.facs)) {
- ACPI_BIOS_WARNING((AE_INFO,
- "32/64X FACS address mismatch in FADT - "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- acpi_gbl_FADT.facs,
- ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));
-
- acpi_gbl_FADT.Xfacs = (u64)acpi_gbl_FADT.facs;
- }
-
- if (acpi_gbl_FADT.dsdt &&
- (acpi_gbl_FADT.Xdsdt != (u64)acpi_gbl_FADT.dsdt)) {
- ACPI_BIOS_WARNING((AE_INFO,
- "32/64X DSDT address mismatch in FADT - "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- acpi_gbl_FADT.dsdt,
- ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));
+ acpi_gbl_FADT.Xfacs = acpi_tb_select_address("FACS",
+ acpi_gbl_FADT.facs,
+ acpi_gbl_FADT.Xfacs);
- acpi_gbl_FADT.Xdsdt = (u64)acpi_gbl_FADT.dsdt;
- }
+ acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT",
+ acpi_gbl_FADT.dsdt,
+ acpi_gbl_FADT.Xdsdt);
/* If Hardware Reduced flag is set, we are all done */
@@ -545,18 +499,95 @@ static void acpi_tb_validate_fadt(void)
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
/*
- * Generate pointer to the 64-bit address, get the register
- * length (width) and the register name
+ * Get the 32-bit and 64-bit addresses, as well as the register
+ * length and register name.
*/
+ address32 = *ACPI_ADD_PTR(u32,
+ &acpi_gbl_FADT,
+ fadt_info_table[i].address32);
+
address64 = ACPI_ADD_PTR(struct acpi_generic_address,
&acpi_gbl_FADT,
fadt_info_table[i].address64);
- length =
- *ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
- fadt_info_table[i].length);
+
+ length = *ACPI_ADD_PTR(u8,
+ &acpi_gbl_FADT,
+ fadt_info_table[i].length);
+
name = fadt_info_table[i].name;
/*
+ * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
+ * generic address structures as necessary. Later code will always use
+ * the 64-bit address structures.
+ *
+ * November 2013:
+ * Now always use the 64-bit address if it is valid (non-zero), in
+ * accordance with the ACPI specification which states that a 64-bit
+ * address supersedes the 32-bit version. This behavior can be
+ * overridden by the acpi_gbl_use32_bit_fadt_addresses flag.
+ *
+ * During 64-bit address construction and verification,
+ * these cases are handled:
+ *
+ * Address32 zero, Address64 [don't care] - Use Address64
+ *
+ * Address32 non-zero, Address64 zero - Copy/use Address32
+ * Address32 non-zero == Address64 non-zero - Use Address64
+ * Address32 non-zero != Address64 non-zero - Warning, use Address64
+ *
+ * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and:
+ * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32
+ *
+ * Note: space_id is always I/O for 32-bit legacy address fields
+ */
+ if (address32) {
+ if (!address64->address) {
+
+ /* 64-bit address is zero, use 32-bit address */
+
+ acpi_tb_init_generic_address(address64,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ *ACPI_ADD_PTR(u8,
+ &acpi_gbl_FADT,
+ fadt_info_table
+ [i].
+ length),
+ (u64)address32,
+ name);
+ } else if (address64->address != (u64)address32) {
+
+ /* Address mismatch */
+
+ ACPI_BIOS_WARNING((AE_INFO,
+ "32/64X address mismatch in FADT/%s: "
+ "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
+ name, address32,
+ ACPI_FORMAT_UINT64
+ (address64->address),
+ acpi_gbl_use32_bit_fadt_addresses
+ ? 32 : 64));
+
+ if (acpi_gbl_use32_bit_fadt_addresses) {
+
+ /* 32-bit address override */
+
+ acpi_tb_init_generic_address(address64,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ *ACPI_ADD_PTR
+ (u8,
+ &acpi_gbl_FADT,
+ fadt_info_table
+ [i].
+ length),
+ (u64)
+ address32,
+ name);
+ }
+ }
+ }
+
+ /*
* For each extended field, check for length mismatch between the
* legacy length field and the corresponding 64-bit X length field.
* Note: If the legacy length field is > 0xFF bits, ignore this
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 3d6bb83aa7e7..6412d3c301cb 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -49,69 +49,11 @@
ACPI_MODULE_NAME("tbutils")
/* Local prototypes */
+static acpi_status acpi_tb_validate_xsdt(acpi_physical_address address);
+
static acpi_physical_address
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_check_xsdt
- *
- * PARAMETERS: address - Pointer to the XSDT
- *
- * RETURN: status
- * AE_OK - XSDT is okay
- * AE_NO_MEMORY - can't map XSDT
- * AE_INVALID_TABLE_LENGTH - invalid table length
- * AE_NULL_ENTRY - XSDT has NULL entry
- *
- * DESCRIPTION: validate XSDT
-******************************************************************************/
-
-static acpi_status
-acpi_tb_check_xsdt(acpi_physical_address address)
-{
- struct acpi_table_header *table;
- u32 length;
- u64 xsdt_entry_address;
- u8 *table_entry;
- u32 table_count;
- int i;
-
- table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
- if (!table)
- return AE_NO_MEMORY;
-
- length = table->length;
- acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
- if (length < sizeof(struct acpi_table_header))
- return AE_INVALID_TABLE_LENGTH;
-
- table = acpi_os_map_memory(address, length);
- if (!table)
- return AE_NO_MEMORY;
-
- /* Calculate the number of tables described in XSDT */
- table_count =
- (u32) ((table->length -
- sizeof(struct acpi_table_header)) / sizeof(u64));
- table_entry =
- ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
- for (i = 0; i < table_count; i++) {
- ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry);
- if (!xsdt_entry_address) {
- /* XSDT has NULL entry */
- break;
- }
- table_entry += sizeof(u64);
- }
- acpi_os_unmap_memory(table, length);
-
- if (i < table_count)
- return AE_NULL_ENTRY;
- else
- return AE_OK;
-}
-
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
@@ -383,7 +325,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
* Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
* Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
*/
- if (table_entry_size == sizeof(u32)) {
+ if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) {
/*
* 32-bit platform, RSDT: Return 32-bit table entry
* 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
@@ -415,6 +357,87 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
/*******************************************************************************
*
+ * FUNCTION: acpi_tb_validate_xsdt
+ *
+ * PARAMETERS: address - Physical address of the XSDT (from RSDP)
+ *
+ * RETURN: Status. AE_OK if the table appears to be valid.
+ *
+ * DESCRIPTION: Validate an XSDT to ensure that it is of minimum size and does
+ * not contain any NULL entries. A problem that is seen in the
+ * field is that the XSDT exists, but is actually useless because
+ * of one or more (or all) NULL entries.
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_tb_validate_xsdt(acpi_physical_address xsdt_address)
+{
+ struct acpi_table_header *table;
+ u8 *next_entry;
+ acpi_physical_address address;
+ u32 length;
+ u32 entry_count;
+ acpi_status status;
+ u32 i;
+
+ /* Get the XSDT length */
+
+ table =
+ acpi_os_map_memory(xsdt_address, sizeof(struct acpi_table_header));
+ if (!table) {
+ return (AE_NO_MEMORY);
+ }
+
+ length = table->length;
+ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+ /*
+ * Minimum XSDT length is the size of the standard ACPI header
+ * plus one physical address entry
+ */
+ if (length < (sizeof(struct acpi_table_header) + ACPI_XSDT_ENTRY_SIZE)) {
+ return (AE_INVALID_TABLE_LENGTH);
+ }
+
+ /* Map the entire XSDT */
+
+ table = acpi_os_map_memory(xsdt_address, length);
+ if (!table) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Get the number of entries and pointer to first entry */
+
+ status = AE_OK;
+ next_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
+ entry_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
+ ACPI_XSDT_ENTRY_SIZE);
+
+ /* Validate each entry (physical address) within the XSDT */
+
+ for (i = 0; i < entry_count; i++) {
+ address =
+ acpi_tb_get_root_table_entry(next_entry,
+ ACPI_XSDT_ENTRY_SIZE);
+ if (!address) {
+
+ /* Detected a NULL entry, XSDT is invalid */
+
+ status = AE_NULL_ENTRY;
+ break;
+ }
+
+ next_entry += ACPI_XSDT_ENTRY_SIZE;
+ }
+
+ /* Unmap table */
+
+ acpi_os_unmap_memory(table, length);
+ return (status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_tb_parse_root_table
*
* PARAMETERS: rsdp - Pointer to the RSDP
@@ -438,16 +461,14 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
u32 table_count;
struct acpi_table_header *table;
acpi_physical_address address;
- acpi_physical_address uninitialized_var(rsdt_address);
u32 length;
u8 *table_entry;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_parse_root_table);
- /*
- * Map the entire RSDP and extract the address of the RSDT or XSDT
- */
+ /* Map the entire RSDP and extract the address of the RSDT or XSDT */
+
rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
if (!rsdp) {
return_ACPI_STATUS(AE_NO_MEMORY);
@@ -457,24 +478,22 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
ACPI_CAST_PTR(struct acpi_table_header,
rsdp));
- /* Differentiate between RSDT and XSDT root tables */
+ /* Use XSDT if present and not overridden. Otherwise, use RSDT */
- if (rsdp->revision > 1 && rsdp->xsdt_physical_address
- && !acpi_rsdt_forced) {
+ if ((rsdp->revision > 1) &&
+ rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) {
/*
- * Root table is an XSDT (64-bit physical addresses). We must use the
- * XSDT if the revision is > 1 and the XSDT pointer is present, as per
- * the ACPI specification.
+ * RSDP contains an XSDT (64-bit physical addresses). We must use
+ * the XSDT if the revision is > 1 and the XSDT pointer is present,
+ * as per the ACPI specification.
*/
address = (acpi_physical_address) rsdp->xsdt_physical_address;
- table_entry_size = sizeof(u64);
- rsdt_address = (acpi_physical_address)
- rsdp->rsdt_physical_address;
+ table_entry_size = ACPI_XSDT_ENTRY_SIZE;
} else {
/* Root table is an RSDT (32-bit physical addresses) */
address = (acpi_physical_address) rsdp->rsdt_physical_address;
- table_entry_size = sizeof(u32);
+ table_entry_size = ACPI_RSDT_ENTRY_SIZE;
}
/*
@@ -483,15 +502,25 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
*/
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
- if (table_entry_size == sizeof(u64)) {
- if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
- /* XSDT has NULL entry, RSDT is used */
- address = rsdt_address;
- table_entry_size = sizeof(u32);
- ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, "
- "using RSDT"));
+ /*
+ * If it is present and used, validate the XSDT for access/size
+ * and ensure that all table entries are at least non-NULL
+ */
+ if (table_entry_size == ACPI_XSDT_ENTRY_SIZE) {
+ status = acpi_tb_validate_xsdt(address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_BIOS_WARNING((AE_INFO,
+ "XSDT is invalid (%s), using RSDT",
+ acpi_format_exception(status)));
+
+ /* Fall back to the RSDT */
+
+ address =
+ (acpi_physical_address) rsdp->rsdt_physical_address;
+ table_entry_size = ACPI_RSDT_ENTRY_SIZE;
}
}
+
/* Map the RSDT/XSDT table header to get the full table length */
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
@@ -501,12 +530,14 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
acpi_tb_print_table_header(address, table);
- /* Get the length of the full table, verify length and map entire table */
-
+ /*
+ * Validate length of the table, and map entire table.
+ * Minimum length table must contain at least one entry.
+ */
length = table->length;
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
- if (length < sizeof(struct acpi_table_header)) {
+ if (length < (sizeof(struct acpi_table_header) + table_entry_size)) {
ACPI_BIOS_ERROR((AE_INFO,
"Invalid table length 0x%X in RSDT/XSDT",
length));
@@ -526,22 +557,21 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
return_ACPI_STATUS(status);
}
- /* Calculate the number of tables described in the root table */
+ /* Get the number of entries and pointer to first entry */
table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
table_entry_size);
+ table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
+
/*
* First two entries in the table array are reserved for the DSDT
* and FACS, which are not actually present in the RSDT/XSDT - they
* come from the FADT
*/
- table_entry =
- ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
acpi_gbl_root_table_list.current_table_count = 2;
- /*
- * Initialize the root table array from the RSDT/XSDT
- */
+ /* Initialize the root table array from the RSDT/XSDT */
+
for (i = 0; i < table_count; i++) {
if (acpi_gbl_root_table_list.current_table_count >=
acpi_gbl_root_table_list.max_table_count) {
@@ -584,7 +614,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
address, NULL, i);
- /* Special case for FADT - get the DSDT and FACS */
+ /* Special case for FADT - validate it then get the DSDT and FACS */
if (ACPI_COMPARE_NAME
(&acpi_gbl_root_table_list.tables[i].signature,
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
index e0a2e2779c2e..2c2b6ae5dfc4 100644
--- a/drivers/acpi/acpica/utaddress.c
+++ b/drivers/acpi/acpica/utaddress.c
@@ -224,10 +224,11 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
while (range_info) {
/*
- * Check if the requested Address/Length overlaps this address_range.
- * Four cases to consider:
+ * Check if the requested address/length overlaps this
+ * address range. There are four cases to consider:
*
- * 1) Input address/length is contained completely in the address range
+ * 1) Input address/length is contained completely in the
+ * address range
* 2) Input address/length overlaps range at the range start
* 3) Input address/length overlaps range at the range end
* 4) Input address/length completely encompasses the range
@@ -244,11 +245,17 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
region_node);
ACPI_WARNING((AE_INFO,
- "0x%p-0x%p %s conflicts with Region %s %d",
+ "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)",
+ acpi_ut_get_region_name(space_id),
ACPI_CAST_PTR(void, address),
ACPI_CAST_PTR(void, end_address),
- acpi_ut_get_region_name(space_id),
- pathname, overlap_count));
+ ACPI_CAST_PTR(void,
+ range_info->
+ start_address),
+ ACPI_CAST_PTR(void,
+ range_info->
+ end_address),
+ pathname));
ACPI_FREE(pathname);
}
}
diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c
index 814267f52715..1851762fc5b5 100644
--- a/drivers/acpi/acpica/utalloc.c
+++ b/drivers/acpi/acpica/utalloc.c
@@ -302,9 +302,13 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
return (AE_BUFFER_OVERFLOW);
case ACPI_ALLOCATE_BUFFER:
-
- /* Allocate a new buffer */
-
+ /*
+ * Allocate a new buffer. We directectly call acpi_os_allocate here to
+ * purposefully bypass the (optionally enabled) internal allocation
+ * tracking mechanism since we only want to track internal
+ * allocations. Note: The caller should use acpi_os_free to free this
+ * buffer created via ACPI_ALLOCATE_BUFFER.
+ */
buffer->pointer = acpi_os_allocate(required_length);
break;
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
index 366bfec4b770..cacd2fd9e665 100644
--- a/drivers/acpi/acpica/utcache.c
+++ b/drivers/acpi/acpica/utcache.c
@@ -248,12 +248,12 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
ACPI_FUNCTION_NAME(os_acquire_object);
if (!cache) {
- return (NULL);
+ return_PTR(NULL);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
if (ACPI_FAILURE(status)) {
- return (NULL);
+ return_PTR(NULL);
}
ACPI_MEM_TRACKING(cache->requests++);
@@ -276,7 +276,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
if (ACPI_FAILURE(status)) {
- return (NULL);
+ return_PTR(NULL);
}
/* Clear (zero) the previously used Object */
@@ -299,15 +299,15 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
if (ACPI_FAILURE(status)) {
- return (NULL);
+ return_PTR(NULL);
}
object = ACPI_ALLOCATE_ZEROED(cache->object_size);
if (!object) {
- return (NULL);
+ return_PTR(NULL);
}
}
- return (object);
+ return_PTR(object);
}
#endif /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 03ae8affe48f..d971c8631263 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -194,9 +194,9 @@ acpi_debug_print(u32 requested_debug_level,
*/
acpi_os_printf("%9s-%04ld ", module_name, line_number);
-#ifdef ACPI_EXEC_APP
+#ifdef ACPI_APPLICATION
/*
- * For acpi_exec only, emit the thread ID and nesting level.
+ * For acpi_exec/iASL only, emit the thread ID and nesting level.
* Note: nesting level is really only useful during a single-thread
* execution. Otherwise, multiple threads will keep resetting the
* level.
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 81f9a9584451..030cb0dc673c 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -388,11 +388,7 @@ acpi_status acpi_ut_init_globals(void)
/* Public globals */
ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
-
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
-
ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
-
ACPI_EXPORT_SYMBOL(acpi_gpe_count)
-
ACPI_EXPORT_SYMBOL(acpi_current_gpe_count)
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
index 75efea0539c1..246ef68681f4 100644
--- a/drivers/acpi/acpica/utxfinit.c
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -122,8 +122,16 @@ acpi_status __init acpi_initialize_subsystem(void)
/* If configured, initialize the AML debugger */
- ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
- return_ACPI_STATUS(status);
+#ifdef ACPI_DEBUGGER
+ status = acpi_db_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Debugger initialization"));
+ return_ACPI_STATUS(status);
+ }
+#endif
+
+ return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem)
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index e55584a072c6..8678dfe5366b 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,7 +34,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index 21ba34a73883..e5bcd919d4e6 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -8,7 +8,6 @@
#include <linux/cper.h>
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
struct apei_exec_context;
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 7dcc8a824aae..1be6f5564485 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -33,7 +33,6 @@
#include <linux/nmi.h>
#include <linux/delay.h>
#include <linux/mm.h>
-#include <acpi/acpi.h>
#include <asm/unaligned.h>
#include "apei-internal.h"
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 46766ef7ef5d..dab7cb7349df 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 5876a49dfd38..470e7542bf31 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -36,8 +36,7 @@
#include <linux/suspend.h>
#include <asm/unaligned.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <linux/power_supply.h>
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 078c4f7fe2dd..10e4964d051a 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -30,7 +30,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
#include <linux/dmi.h>
#include "internal.h"
@@ -323,6 +322,56 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
},
},
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP ProBook 2013 models",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
+ DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP EliteBook 2013 models",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+ DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP ZBook 14",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP ZBook 15",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP ZBook 17",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "HP EliteBook 8780w",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
+ },
+ },
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 0710004055c8..384da5ab5955 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -37,8 +37,6 @@
#include <asm/mpspec.h>
#endif
#include <linux/pci.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#include <acpi/apei.h>
#include <linux/dmi.h>
#include <linux/suspend.h>
@@ -52,9 +50,6 @@ struct acpi_device *acpi_root;
struct proc_dir_entry *acpi_root_dir;
EXPORT_SYMBOL(acpi_root_dir);
-#define STRUCT_TO_INT(s) (*((int*)&s))
-
-
#ifdef CONFIG_X86
static int set_copy_dsdt(const struct dmi_system_id *id)
{
@@ -115,18 +110,16 @@ int acpi_bus_get_status(struct acpi_device *device)
if (ACPI_FAILURE(status))
return -ENODEV;
- STRUCT_TO_INT(device->status) = (int) sta;
+ acpi_set_device_status(device, sta);
if (device->status.functional && !device->status.present) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
"functional but not present;\n",
- device->pnp.bus_id,
- (u32) STRUCT_TO_INT(device->status)));
+ device->pnp.bus_id, (u32)sta));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
- device->pnp.bus_id,
- (u32) STRUCT_TO_INT(device->status)));
+ device->pnp.bus_id, (u32)sta));
return 0;
}
EXPORT_SYMBOL(acpi_bus_get_status);
@@ -339,58 +332,6 @@ static void acpi_bus_osc_support(void)
Notification Handling
-------------------------------------------------------------------------- */
-static void acpi_bus_check_device(acpi_handle handle)
-{
- struct acpi_device *device;
- acpi_status status;
- struct acpi_device_status old_status;
-
- if (acpi_bus_get_device(handle, &device))
- return;
- if (!device)
- return;
-
- old_status = device->status;
-
- /*
- * Make sure this device's parent is present before we go about
- * messing with the device.
- */
- if (device->parent && !device->parent->status.present) {
- device->status = device->parent->status;
- return;
- }
-
- status = acpi_bus_get_status(device);
- if (ACPI_FAILURE(status))
- return;
-
- if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
- return;
-
- /*
- * Device Insertion/Removal
- */
- if ((device->status.present) && !(old_status.present)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
- /* TBD: Handle device insertion */
- } else if (!(device->status.present) && (old_status.present)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
- /* TBD: Handle device removal */
- }
-}
-
-static void acpi_bus_check_scope(acpi_handle handle)
-{
- /* Status Change? */
- acpi_bus_check_device(handle);
-
- /*
- * TBD: Enumerate child devices within this device's scope and
- * run acpi_bus_check_device()'s on them.
- */
-}
-
/**
* acpi_bus_notify
* ---------------
@@ -407,19 +348,11 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- acpi_bus_check_scope(handle);
- /*
- * TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
- */
+ /* TBD */
break;
case ACPI_NOTIFY_DEVICE_CHECK:
- acpi_bus_check_device(handle);
- /*
- * TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
- */
+ /* TBD */
break;
case ACPI_NOTIFY_DEVICE_WAKE:
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index c971929d75c2..11c11f6b8fa1 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -31,8 +31,7 @@
#include <linux/seq_file.h>
#include <linux/input.h>
#include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <acpi/button.h>
#define PREFIX "ACPI: "
@@ -101,7 +100,6 @@ struct acpi_button {
struct input_dev *input;
char phys[32]; /* for input device */
unsigned long pushed;
- bool wakeup_enabled;
};
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -407,16 +405,6 @@ static int acpi_button_add(struct acpi_device *device)
lid_device = device;
}
- if (device->wakeup.flags.valid) {
- /* Button's GPE is run-wake GPE */
- acpi_enable_gpe(device->wakeup.gpe_device,
- device->wakeup.gpe_number);
- if (!device_may_wakeup(&device->dev)) {
- device_set_wakeup_enable(&device->dev, true);
- button->wakeup_enabled = true;
- }
- }
-
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
return 0;
@@ -433,13 +421,6 @@ static int acpi_button_remove(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
- if (device->wakeup.flags.valid) {
- acpi_disable_gpe(device->wakeup.gpe_device,
- device->wakeup.gpe_number);
- if (button->wakeup_enabled)
- device_set_wakeup_enable(&device->dev, false);
- }
-
acpi_button_remove_fs(device);
input_unregister_device(button->input);
kfree(button);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index e23151667655..0b6ae6eb5c4a 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -27,8 +27,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/acpi.h>
-
-#include "internal.h"
+#include <linux/container.h>
#include "internal.h"
@@ -44,19 +43,65 @@ static const struct acpi_device_id container_device_ids[] = {
{"", 0},
};
-static int container_device_attach(struct acpi_device *device,
+static int acpi_container_offline(struct container_dev *cdev)
+{
+ struct acpi_device *adev = ACPI_COMPANION(&cdev->dev);
+ struct acpi_device *child;
+
+ /* Check all of the dependent devices' physical companions. */
+ list_for_each_entry(child, &adev->children, node)
+ if (!acpi_scan_is_offline(child, false))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void acpi_container_release(struct device *dev)
+{
+ kfree(to_container_dev(dev));
+}
+
+static int container_device_attach(struct acpi_device *adev,
const struct acpi_device_id *not_used)
{
- /* This is necessary for container hotplug to work. */
+ struct container_dev *cdev;
+ struct device *dev;
+ int ret;
+
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ if (!cdev)
+ return -ENOMEM;
+
+ cdev->offline = acpi_container_offline;
+ dev = &cdev->dev;
+ dev->bus = &container_subsys;
+ dev_set_name(dev, "%s", dev_name(&adev->dev));
+ ACPI_COMPANION_SET(dev, adev);
+ dev->release = acpi_container_release;
+ ret = device_register(dev);
+ if (ret)
+ return ret;
+
+ adev->driver_data = dev;
return 1;
}
+static void container_device_detach(struct acpi_device *adev)
+{
+ struct device *dev = acpi_driver_data(adev);
+
+ adev->driver_data = NULL;
+ if (dev)
+ device_unregister(dev);
+}
+
static struct acpi_scan_handler container_handler = {
.ids = container_device_ids,
.attach = container_device_attach,
+ .detach = container_device_detach,
.hotplug = {
.enabled = true,
- .mode = AHM_CONTAINER,
+ .demand_offline = true,
},
};
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
index 12b62f2cdb3f..c68e72414a67 100644
--- a/drivers/acpi/custom_method.c
+++ b/drivers/acpi/custom_method.c
@@ -7,7 +7,7 @@
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include "internal.h"
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c
index b55d6a20dc0e..6b1919f6bd82 100644
--- a/drivers/acpi/debugfs.c
+++ b/drivers/acpi/debugfs.c
@@ -5,7 +5,7 @@
#include <linux/export.h>
#include <linux/init.h>
#include <linux/debugfs.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("debugfs");
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index b3480cf7db1a..d49f1e464703 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -256,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device)
return -EINVAL;
device->power.state = ACPI_STATE_UNKNOWN;
+ if (!acpi_device_is_present(device))
+ return 0;
result = acpi_device_get_power(device, &state);
if (result)
@@ -302,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device)
return ret;
}
-int acpi_bus_update_power(acpi_handle handle, int *state_p)
+int acpi_device_update_power(struct acpi_device *device, int *state_p)
{
- struct acpi_device *device;
int state;
int result;
- result = acpi_bus_get_device(handle, &device);
- if (result)
+ if (device->power.state == ACPI_STATE_UNKNOWN) {
+ result = acpi_bus_init_power(device);
+ if (!result && state_p)
+ *state_p = device->power.state;
+
return result;
+ }
result = acpi_device_get_power(device, &state);
if (result)
@@ -338,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
return 0;
}
+
+int acpi_bus_update_power(acpi_handle handle, int *state_p)
+{
+ struct acpi_device *device;
+ int result;
+
+ result = acpi_bus_get_device(handle, &device);
+ return result ? result : acpi_device_update_power(device, state_p);
+}
EXPORT_SYMBOL_GPL(acpi_bus_update_power);
bool acpi_bus_power_manageable(acpi_handle handle)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index dcd73ccb514c..c431c88faaff 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -32,8 +32,8 @@
#include <linux/jiffies.h>
#include <linux/stddef.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+
+#include "internal.h"
#define PREFIX "ACPI: "
@@ -323,14 +323,11 @@ static int dock_present(struct dock_station *ds)
*/
static void dock_create_acpi_device(acpi_handle handle)
{
- struct acpi_device *device;
+ struct acpi_device *device = NULL;
int ret;
- if (acpi_bus_get_device(handle, &device)) {
- /*
- * no device created for this object,
- * so we should create one.
- */
+ acpi_bus_get_device(handle, &device);
+ if (!acpi_device_enumerated(device)) {
ret = acpi_bus_scan(handle);
if (ret)
pr_debug("error adding bus, %x\n", -ret);
@@ -898,9 +895,6 @@ find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
void __init acpi_dock_init(void)
{
- if (acpi_disabled)
- return;
-
/* look for dock stations and bays */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index ba5b56db9d27..959d41acc108 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -39,10 +39,9 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
-#include <asm/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <asm/io.h>
#include "internal.h"
@@ -91,10 +90,6 @@ static unsigned int ec_storm_threshold __read_mostly = 8;
module_param(ec_storm_threshold, uint, 0644);
MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
-/* If we find an EC via the ECDT, we need to keep a ptr to its context */
-/* External interfaces use first EC only, so remember */
-typedef int (*acpi_ec_query_func) (void *data);
-
struct acpi_ec_query_handler {
struct list_head node;
acpi_ec_query_func func;
@@ -387,27 +382,6 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
return acpi_ec_transaction(ec, &t);
}
-/*
- * Externally callable EC access functions. For now, assume 1 EC only
- */
-int ec_burst_enable(void)
-{
- if (!first_ec)
- return -ENODEV;
- return acpi_ec_burst_enable(first_ec);
-}
-
-EXPORT_SYMBOL(ec_burst_enable);
-
-int ec_burst_disable(void)
-{
- if (!first_ec)
- return -ENODEV;
- return acpi_ec_burst_disable(first_ec);
-}
-
-EXPORT_SYMBOL(ec_burst_disable);
-
int ec_read(u8 addr, u8 *val)
{
int err;
@@ -779,9 +753,9 @@ static int ec_install_handlers(struct acpi_ec *ec)
pr_err("Fail in evaluating the _REG object"
" of EC device. Broken bios is suspected.\n");
} else {
+ acpi_disable_gpe(NULL, ec->gpe);
acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler);
- acpi_disable_gpe(NULL, ec->gpe);
return -ENODEV;
}
}
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 4e7b798900f2..b4c216bab22b 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -105,7 +105,7 @@ static const struct file_operations acpi_ec_io_ops = {
.llseek = default_llseek,
};
-int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
+static int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
{
struct dentry *dev_dir;
char name[64];
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index cae3b387b867..ef2d730734dc 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/gfp.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <net/netlink.h>
#include <net/genetlink.h>
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index ba3da88cee45..1fb62900f32a 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -29,8 +29,7 @@
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index a22a295edb69..0c789224d40d 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -37,7 +37,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
return -ENODEV;
- if (type && type->match && type->find_device) {
+ if (type && type->match && type->find_companion) {
down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem);
@@ -82,109 +82,74 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
#define FIND_CHILD_MIN_SCORE 1
#define FIND_CHILD_MAX_SCORE 2
-static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used,
- void *not_used, void **ret_p)
-{
- struct acpi_device *adev = NULL;
-
- acpi_bus_get_device(handle, &adev);
- if (adev) {
- *ret_p = handle;
- return AE_CTRL_TERMINATE;
- }
- return AE_OK;
-}
-
-static int do_find_child_checks(acpi_handle handle, bool is_bridge)
+static int find_child_checks(struct acpi_device *adev, bool check_children)
{
bool sta_present = true;
unsigned long long sta;
acpi_status status;
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+ status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
if (status == AE_NOT_FOUND)
sta_present = false;
else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
return -ENODEV;
- if (is_bridge) {
- void *test = NULL;
+ if (check_children && list_empty(&adev->children))
+ return -ENODEV;
- /* Check if this object has at least one child device. */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
- acpi_dev_present, NULL, NULL, &test);
- if (!test)
- return -ENODEV;
- }
return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
}
-struct find_child_context {
- u64 addr;
- bool is_bridge;
- acpi_handle ret;
- int ret_score;
-};
-
-static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used,
- void *data, void **not_used)
-{
- struct find_child_context *context = data;
- unsigned long long addr;
- acpi_status status;
- int score;
-
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
- if (ACPI_FAILURE(status) || addr != context->addr)
- return AE_OK;
-
- if (!context->ret) {
- /* This is the first matching object. Save its handle. */
- context->ret = handle;
- return AE_OK;
- }
- /*
- * There is more than one matching object with the same _ADR value.
- * That really is unexpected, so we are kind of beyond the scope of the
- * spec here. We have to choose which one to return, though.
- *
- * First, check if the previously found object is good enough and return
- * its handle if so. Second, check the same for the object that we've
- * just found.
- */
- if (!context->ret_score) {
- score = do_find_child_checks(context->ret, context->is_bridge);
- if (score == FIND_CHILD_MAX_SCORE)
- return AE_CTRL_TERMINATE;
- else
- context->ret_score = score;
- }
- score = do_find_child_checks(handle, context->is_bridge);
- if (score == FIND_CHILD_MAX_SCORE) {
- context->ret = handle;
- return AE_CTRL_TERMINATE;
- } else if (score > context->ret_score) {
- context->ret = handle;
- context->ret_score = score;
- }
- return AE_OK;
-}
-
-acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
+struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
+ u64 address, bool check_children)
{
- if (parent) {
- struct find_child_context context = {
- .addr = addr,
- .is_bridge = is_bridge,
- };
-
- acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child,
- NULL, &context, NULL);
- return context.ret;
+ struct acpi_device *adev, *ret = NULL;
+ int ret_score = 0;
+
+ if (!parent)
+ return NULL;
+
+ list_for_each_entry(adev, &parent->children, node) {
+ unsigned long long addr;
+ acpi_status status;
+ int score;
+
+ status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR,
+ NULL, &addr);
+ if (ACPI_FAILURE(status) || addr != address)
+ continue;
+
+ if (!ret) {
+ /* This is the first matching object. Save it. */
+ ret = adev;
+ continue;
+ }
+ /*
+ * There is more than one matching device object with the same
+ * _ADR value. That really is unexpected, so we are kind of
+ * beyond the scope of the spec here. We have to choose which
+ * one to return, though.
+ *
+ * First, check if the previously found object is good enough
+ * and return it if so. Second, do the same for the object that
+ * we've just found.
+ */
+ if (!ret_score) {
+ ret_score = find_child_checks(ret, check_children);
+ if (ret_score == FIND_CHILD_MAX_SCORE)
+ return ret;
+ }
+ score = find_child_checks(adev, check_children);
+ if (score == FIND_CHILD_MAX_SCORE) {
+ return adev;
+ } else if (score > ret_score) {
+ ret = adev;
+ ret_score = score;
+ }
}
- return NULL;
+ return ret;
}
-EXPORT_SYMBOL_GPL(acpi_find_child);
+EXPORT_SYMBOL_GPL(acpi_find_child_device);
static void acpi_physnode_link_name(char *buf, unsigned int node_id)
{
@@ -195,9 +160,8 @@ static void acpi_physnode_link_name(char *buf, unsigned int node_id)
strcpy(buf, PHYSICAL_NODE_STRING);
}
-int acpi_bind_one(struct device *dev, acpi_handle handle)
+int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
{
- struct acpi_device *acpi_dev = NULL;
struct acpi_device_physical_node *physical_node, *pn;
char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
struct list_head *physnode_list;
@@ -205,14 +169,12 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
int retval = -EINVAL;
if (ACPI_COMPANION(dev)) {
- if (handle) {
+ if (acpi_dev) {
dev_warn(dev, "ACPI companion already set\n");
return -EINVAL;
} else {
acpi_dev = ACPI_COMPANION(dev);
}
- } else {
- acpi_bus_get_device(handle, &acpi_dev);
}
if (!acpi_dev)
return -EINVAL;
@@ -322,29 +284,22 @@ int acpi_unbind_one(struct device *dev)
}
EXPORT_SYMBOL_GPL(acpi_unbind_one);
-void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr)
-{
- struct acpi_device *adev;
-
- if (!acpi_bus_get_device(acpi_get_child(parent, addr), &adev))
- ACPI_COMPANION_SET(dev, adev);
-}
-EXPORT_SYMBOL_GPL(acpi_preset_companion);
-
static int acpi_platform_notify(struct device *dev)
{
struct acpi_bus_type *type = acpi_get_bus_type(dev);
- acpi_handle handle;
int ret;
ret = acpi_bind_one(dev, NULL);
if (ret && type) {
- ret = type->find_device(dev, &handle);
- if (ret) {
+ struct acpi_device *adev;
+
+ adev = type->find_companion(dev);
+ if (!adev) {
DBG("Unable to get handle for %s\n", dev_name(dev));
+ ret = -ENODEV;
goto out;
}
- ret = acpi_bind_one(dev, handle);
+ ret = acpi_bind_one(dev, adev);
if (ret)
goto out;
}
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 13b1d39d7cdf..aafe3ca829c2 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -25,8 +25,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#include <acpi/hed.h>
static struct acpi_device_id acpi_hed_ids[] = {
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index a29739c0ba79..dedbb2d802f1 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -28,7 +28,6 @@ int init_acpi_device_notify(void);
int acpi_scan_init(void);
void acpi_pci_root_init(void);
void acpi_pci_link_init(void);
-void acpi_pci_root_hp_init(void);
void acpi_processor_init(void);
void acpi_platform_init(void);
int acpi_sysfs_init(void);
@@ -73,6 +72,9 @@ void acpi_lpss_init(void);
static inline void acpi_lpss_init(void) {}
#endif
+bool acpi_queue_hotplug_work(struct work_struct *work);
+bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+
/* --------------------------------------------------------------------------
Device Node Initialization / Removal
-------------------------------------------------------------------------- */
@@ -85,9 +87,9 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
int type, unsigned long long sta);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
-int acpi_bind_one(struct device *dev, acpi_handle handle);
+int acpi_bind_one(struct device *dev, struct acpi_device *adev);
int acpi_unbind_one(struct device *dev);
-void acpi_bus_device_eject(void *data, u32 ost_src);
+bool acpi_device_is_present(struct acpi_device *adev);
/* --------------------------------------------------------------------------
Power Resource
@@ -105,6 +107,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
int acpi_power_on_resources(struct acpi_device *device, int state);
int acpi_power_transition(struct acpi_device *device, int state);
+int acpi_device_update_power(struct acpi_device *device, int *state_p);
+
int acpi_wakeup_device_init(void);
void acpi_early_processor_set_pdc(void);
@@ -127,12 +131,21 @@ struct acpi_ec {
extern struct acpi_ec *first_ec;
+/* If we find an EC via the ECDT, we need to keep a ptr to its context */
+/* External interfaces use first EC only, so remember */
+typedef int (*acpi_ec_query_func) (void *data);
+
int acpi_ec_init(void);
int acpi_ec_ecdt_probe(void);
int acpi_boot_ec_enable(void);
void acpi_ec_block_transactions(void);
void acpi_ec_unblock_transactions(void);
void acpi_ec_unblock_transactions_early(void);
+int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
+ acpi_handle handle, acpi_ec_query_func func,
+ void *data);
+void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
+
/*--------------------------------------------------------------------------
Suspend/Resume
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a2343a1d9e0b..9e6816ef280a 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -29,7 +29,6 @@
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/numa.h>
-#include <acpi/acpi_bus.h>
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c
index 386a9fe497b4..de4fe03873c5 100644
--- a/drivers/acpi/nvs.c
+++ b/drivers/acpi/nvs.c
@@ -12,7 +12,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
+
+#include "internal.h"
/* ACPI NVS regions, APEI may use it */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 54a20ff4b864..fc1aa7909690 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -39,7 +39,6 @@
#include <linux/workqueue.h>
#include <linux/nmi.h>
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
#include <linux/efi.h>
#include <linux/ioport.h>
#include <linux/list.h>
@@ -49,9 +48,6 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/processor.h>
#include "internal.h"
#define _COMPONENT ACPI_OS_SERVICES
@@ -544,7 +540,7 @@ 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)
+static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
{
u8 sum = 0;
u8 *end = buffer + length;
@@ -1215,6 +1211,10 @@ acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src)
return AE_OK;
}
+bool acpi_queue_hotplug_work(struct work_struct *work)
+{
+ return queue_work(kacpi_hotplug_wq, work);
+}
acpi_status
acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
@@ -1282,7 +1282,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
jiffies = MAX_SCHEDULE_TIMEOUT;
else
jiffies = msecs_to_jiffies(timeout);
-
+
ret = down_timeout(sem, jiffies);
if (ret)
status = AE_TIME;
@@ -1794,7 +1794,7 @@ acpi_status __init acpi_os_initialize1(void)
{
kacpid_wq = alloc_workqueue("kacpid", 0, 1);
kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
- kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
+ kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 41c5e1b799ef..52d45ea2bc4f 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -37,8 +37,6 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 2652a614deeb..9418c7a1f786 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -39,9 +39,9 @@
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include "internal.h"
#define PREFIX "ACPI: "
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 5b01bd6d5ea0..c1c4102e6478 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -35,9 +35,7 @@
#include <linux/pci-aspm.h>
#include <linux/acpi.h>
#include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/apei.h>
+#include <acpi/apei.h> /* for acpi_hest_init() */
#include "internal.h"
@@ -51,6 +49,12 @@ static int acpi_pci_root_add(struct acpi_device *device,
const struct acpi_device_id *not_used);
static void acpi_pci_root_remove(struct acpi_device *device);
+static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
+{
+ acpiphp_check_host_bridge(adev->handle);
+ return 0;
+}
+
#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
| OSC_PCI_ASPM_SUPPORT \
| OSC_PCI_CLOCK_PM_SUPPORT \
@@ -66,7 +70,8 @@ static struct acpi_scan_handler pci_root_handler = {
.attach = acpi_pci_root_add,
.detach = acpi_pci_root_remove,
.hotplug = {
- .ignore = true,
+ .enabled = true,
+ .scan_dependent = acpi_pci_root_scan_dependent,
},
};
@@ -630,116 +635,9 @@ static void acpi_pci_root_remove(struct acpi_device *device)
void __init acpi_pci_root_init(void)
{
acpi_hest_init();
-
- if (!acpi_pci_disabled) {
- pci_acpi_crs_quirks();
- acpi_scan_add_handler(&pci_root_handler);
- }
-}
-/* Support root bridge hotplug */
-
-static void handle_root_bridge_insertion(acpi_handle handle)
-{
- struct acpi_device *device;
-
- if (!acpi_bus_get_device(handle, &device)) {
- dev_printk(KERN_DEBUG, &device->dev,
- "acpi device already exists; ignoring notify\n");
+ if (acpi_pci_disabled)
return;
- }
-
- if (acpi_bus_scan(handle))
- acpi_handle_err(handle, "cannot add bridge to acpi list\n");
-}
-
-static void hotplug_event_root(void *data, u32 type)
-{
- acpi_handle handle = data;
- struct acpi_pci_root *root;
-
- acpi_scan_lock_acquire();
-
- root = acpi_pci_find_root(handle);
-
- switch (type) {
- case ACPI_NOTIFY_BUS_CHECK:
- /* bus enumerate */
- acpi_handle_printk(KERN_DEBUG, handle,
- "Bus check notify on %s\n", __func__);
- if (root)
- acpiphp_check_host_bridge(handle);
- else
- handle_root_bridge_insertion(handle);
-
- break;
-
- case ACPI_NOTIFY_DEVICE_CHECK:
- /* device check */
- acpi_handle_printk(KERN_DEBUG, handle,
- "Device check notify on %s\n", __func__);
- if (!root)
- handle_root_bridge_insertion(handle);
- break;
-
- case ACPI_NOTIFY_EJECT_REQUEST:
- /* request device eject */
- acpi_handle_printk(KERN_DEBUG, handle,
- "Device eject notify on %s\n", __func__);
- if (!root)
- break;
-
- get_device(&root->device->dev);
-
- acpi_scan_lock_release();
-
- acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST);
- return;
- default:
- acpi_handle_warn(handle,
- "notify_handler: unknown event type 0x%x\n",
- type);
- break;
- }
-
- acpi_scan_lock_release();
-}
-
-static void handle_hotplug_event_root(acpi_handle handle, u32 type,
- void *context)
-{
- acpi_hotplug_execute(hotplug_event_root, handle, type);
-}
-
-static acpi_status __init
-find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- acpi_status status;
- int *count = (int *)context;
-
- if (!acpi_is_root_bridge(handle))
- return AE_OK;
-
- (*count)++;
-
- status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_root, NULL);
- if (ACPI_FAILURE(status))
- acpi_handle_printk(KERN_DEBUG, handle,
- "notify handler is not installed, exit status: %u\n",
- (unsigned int)status);
- else
- acpi_handle_printk(KERN_DEBUG, handle,
- "notify handler is installed\n");
-
- return AE_OK;
-}
-
-void __init acpi_pci_root_hp_init(void)
-{
- int num = 0;
-
- acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
- printk(KERN_DEBUG "Found %d acpi root devices\n", num);
+ pci_acpi_crs_quirks();
+ acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index d678a180ca2a..139d9e479370 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <linux/pci-acpi.h>
static bool debug;
static int check_sta_before_sun;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index c2ad391d8041..ad7da686e6e6 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -42,8 +42,7 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/sysfs.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include "sleep.h"
#include "internal.h"
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 6a5b152ad4d0..50fe34ffe932 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -3,12 +3,11 @@
#include <linux/export.h>
#include <linux/suspend.h>
#include <linux/bcd.h>
+#include <linux/acpi.h>
#include <asm/uaccess.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
#include "sleep.h"
+#include "internal.h"
#define _COMPONENT ACPI_SYSTEM_COMPONENT
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index b3171f30b319..34e7b3c6a08d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -10,8 +10,7 @@
#include <linux/export.h>
#include <linux/dmi.h>
#include <linux/slab.h>
-
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <acpi/processor.h>
#include "internal.h"
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 146ab7e2b81d..c1c35623550f 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -224,9 +224,9 @@ static int __acpi_processor_start(struct acpi_device *device)
static int acpi_processor_start(struct device *dev)
{
- struct acpi_device *device;
+ struct acpi_device *device = ACPI_COMPANION(dev);
- if (acpi_bus_get_device(ACPI_HANDLE(dev), &device))
+ if (!device)
return -ENODEV;
return __acpi_processor_start(device);
@@ -234,10 +234,10 @@ static int acpi_processor_start(struct device *dev)
static int acpi_processor_stop(struct device *dev)
{
- struct acpi_device *device;
+ struct acpi_device *device = ACPI_COMPANION(dev);
struct acpi_processor *pr;
- if (acpi_bus_get_device(ACPI_HANDLE(dev), &device))
+ if (!device)
return 0;
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f90c56c8379e..3dca36d4ad26 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -35,6 +35,7 @@
#include <linux/clockchips.h>
#include <linux/cpuidle.h>
#include <linux/syscore_ops.h>
+#include <acpi/processor.h>
/*
* Include the apic definitions for x86 to have the APIC timer related defines
@@ -46,9 +47,6 @@
#include <asm/apic.h>
#endif
-#include <acpi/acpi_bus.h>
-#include <acpi/processor.h>
-
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
@@ -213,7 +211,7 @@ static int acpi_processor_suspend(void)
static void acpi_processor_resume(void)
{
- u32 resumed_bm_rld;
+ u32 resumed_bm_rld = 0;
acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
if (resumed_bm_rld == saved_bm_rld)
@@ -598,7 +596,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C2:
if (!cx->address)
break;
- cx->valid = 1;
+ cx->valid = 1;
break;
case ACPI_STATE_C3:
@@ -780,6 +778,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (unlikely(!pr))
return -EINVAL;
+#ifdef CONFIG_HOTPLUG_CPU
+ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+ !pr->flags.has_cst &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+ return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
+#endif
+
/*
* Must be done before busmaster disable as we might need to
* access HPET !
@@ -821,6 +826,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (unlikely(!pr))
return -EINVAL;
+#ifdef CONFIG_HOTPLUG_CPU
+ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+ !pr->flags.has_cst &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+ return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
+#endif
+
if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
if (drv->safe_state_index >= 0) {
return drv->states[drv->safe_state_index].enter(dev,
@@ -917,12 +929,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
if (!cx->valid)
continue;
-#ifdef CONFIG_HOTPLUG_CPU
- if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
- !pr->flags.has_cst &&
- !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
- continue;
-#endif
per_cpu(acpi_cstate[count], dev->cpu) = cx;
count++;
@@ -930,8 +936,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
break;
}
- dev->state_count = count;
-
if (!count)
return -EINVAL;
@@ -972,13 +976,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
if (!cx->valid)
continue;
-#ifdef CONFIG_HOTPLUG_CPU
- if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
- !pr->flags.has_cst &&
- !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
- continue;
-#endif
-
state = &drv->states[count];
snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 60a7c28fc167..ff90054f04fd 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -31,15 +31,12 @@
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/slab.h>
-
+#include <linux/acpi.h>
+#include <acpi/processor.h>
#ifdef CONFIG_X86
#include <asm/cpufeature.h>
#endif
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index d1d2e7fb5b30..e003663b2f8e 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -30,12 +30,9 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
-
-#include <asm/uaccess.h>
-
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
#include <acpi/processor.h>
-#include <acpi/acpi_drivers.h>
+#include <asm/uaccess.h>
#define PREFIX "ACPI: "
@@ -186,14 +183,14 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
#endif
-/* thermal coolign device callbacks */
+/* thermal cooling device callbacks */
static int acpi_processor_max_state(struct acpi_processor *pr)
{
int max_state = 0;
/*
* There exists four states according to
- * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3
+ * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3
*/
max_state += cpufreq_get_max_state(pr->id);
if (pr->flags.throttling)
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index e7dd2c1fee79..28baa05b8018 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -32,14 +32,11 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/cpufreq.h>
-
+#include <linux/acpi.h>
+#include <acpi/processor.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index b78bc605837e..26e5b5060523 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -8,8 +8,7 @@
* the Free Software Foundation version 2.
*/
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/delay.h>
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index fd39459926b1..e00365ccb897 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -12,13 +12,12 @@
#include <linux/dmi.h>
#include <linux/nls.h>
-#include <acpi/acpi_drivers.h>
+#include <asm/pgtable.h>
#include "internal.h"
#define _COMPONENT ACPI_BUS_COMPONENT
ACPI_MODULE_NAME("scan");
-#define STRUCT_TO_INT(s) (*((int*)&s))
extern struct acpi_device *acpi_root;
#define ACPI_BUS_CLASS "system_bus"
@@ -27,6 +26,8 @@ extern struct acpi_device *acpi_root;
#define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent)
+#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page)
+
/*
* If set, devices will be hot-removed even if they cannot be put offline
* gracefully (from the kernel's standpoint).
@@ -85,6 +86,9 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
* Creates hid/cid(s) string needed for modalias and uevent
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
* char *modalias: "acpi:IBM0001:ACPI0001"
+ * Return: 0: no _HID and no _CID
+ * -EINVAL: output error
+ * -ENOMEM: output is truncated
*/
static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
int size)
@@ -101,8 +105,10 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
count = snprintf(&modalias[len], size, "%s:", id->id);
- if (count < 0 || count >= size)
- return -EINVAL;
+ if (count < 0)
+ return EINVAL;
+ if (count >= size)
+ return -ENOMEM;
len += count;
size -= count;
}
@@ -111,20 +117,96 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
return len;
}
+/*
+ * Creates uevent modalias field for ACPI enumerated devices.
+ * Because the other buses does not support ACPI HIDs & CIDs.
+ * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
+ * "acpi:IBM0001:ACPI0001"
+ */
+int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct acpi_device *acpi_dev;
+ int len;
+
+ acpi_dev = ACPI_COMPANION(dev);
+ if (!acpi_dev)
+ return -ENODEV;
+
+ /* Fall back to bus specific way of modalias exporting */
+ if (list_empty(&acpi_dev->pnp.ids))
+ return -ENODEV;
+
+ if (add_uevent_var(env, "MODALIAS="))
+ return -ENOMEM;
+ len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
+ sizeof(env->buf) - env->buflen);
+ if (len <= 0)
+ return len;
+ env->buflen += len;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
+
+/*
+ * Creates modalias sysfs attribute for ACPI enumerated devices.
+ * Because the other buses does not support ACPI HIDs & CIDs.
+ * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
+ * "acpi:IBM0001:ACPI0001"
+ */
+int acpi_device_modalias(struct device *dev, char *buf, int size)
+{
+ struct acpi_device *acpi_dev;
+ int len;
+
+ acpi_dev = ACPI_COMPANION(dev);
+ if (!acpi_dev)
+ return -ENODEV;
+
+ /* Fall back to bus specific way of modalias exporting */
+ if (list_empty(&acpi_dev->pnp.ids))
+ return -ENODEV;
+
+ len = create_modalias(acpi_dev, buf, size -1);
+ if (len <= 0)
+ return len;
+ buf[len++] = '\n';
+ return len;
+}
+EXPORT_SYMBOL_GPL(acpi_device_modalias);
+
static ssize_t
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
int len;
- /* Device has no HID and no CID or string is >1024 */
len = create_modalias(acpi_dev, buf, 1024);
if (len <= 0)
- return 0;
+ return len;
buf[len++] = '\n';
return len;
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
+{
+ struct acpi_device_physical_node *pn;
+ bool offline = true;
+
+ mutex_lock(&adev->physical_node_lock);
+
+ list_for_each_entry(pn, &adev->physical_node_list, node)
+ if (device_supports_offline(pn->dev) && !pn->dev->offline) {
+ if (uevent)
+ kobject_uevent(&pn->dev->kobj, KOBJ_CHANGE);
+
+ offline = false;
+ break;
+ }
+
+ mutex_unlock(&adev->physical_node_lock);
+ return offline;
+}
+
static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
void **ret_p)
{
@@ -195,19 +277,11 @@ static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,
return AE_OK;
}
-static int acpi_scan_hot_remove(struct acpi_device *device)
+static int acpi_scan_try_to_offline(struct acpi_device *device)
{
acpi_handle handle = device->handle;
- struct device *errdev;
+ struct device *errdev = NULL;
acpi_status status;
- unsigned long long sta;
-
- /* If there is no handle, the device node has been unregistered. */
- if (!handle) {
- dev_dbg(&device->dev, "ACPI handle missing\n");
- put_device(&device->dev);
- return -EINVAL;
- }
/*
* Carry out two passes here and ignore errors in the first pass,
@@ -218,7 +292,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
*
* If the first pass is successful, the second one isn't needed, though.
*/
- errdev = NULL;
status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
NULL, acpi_bus_offline, (void *)false,
(void **)&errdev);
@@ -226,7 +299,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
dev_warn(errdev, "Offline disabled.\n");
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_online, NULL, NULL, NULL);
- put_device(&device->dev);
return -EPERM;
}
acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev);
@@ -245,20 +317,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
acpi_walk_namespace(ACPI_TYPE_ANY, handle,
ACPI_UINT32_MAX, acpi_bus_online,
NULL, NULL, NULL);
- put_device(&device->dev);
return -EBUSY;
}
}
+ return 0;
+}
+
+static int acpi_scan_hot_remove(struct acpi_device *device)
+{
+ acpi_handle handle = device->handle;
+ unsigned long long sta;
+ acpi_status status;
+
+ if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) {
+ if (!acpi_scan_is_offline(device, true))
+ return -EBUSY;
+ } else {
+ int error = acpi_scan_try_to_offline(device);
+ if (error)
+ return error;
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Hot-removing device %s...\n", dev_name(&device->dev)));
acpi_bus_trim(device);
- /* Device node has been unregistered. */
- put_device(&device->dev);
- device = NULL;
-
acpi_evaluate_lck(handle, 0);
/*
* TBD: _EJD support.
@@ -285,115 +369,127 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
return 0;
}
-void acpi_bus_device_eject(void *data, u32 ost_src)
+static int acpi_scan_device_not_present(struct acpi_device *adev)
{
- struct acpi_device *device = data;
- acpi_handle handle = device->handle;
- u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
- int error;
+ if (!acpi_device_enumerated(adev)) {
+ dev_warn(&adev->dev, "Still not present\n");
+ return -EALREADY;
+ }
+ acpi_bus_trim(adev);
+ return 0;
+}
- lock_device_hotplug();
- mutex_lock(&acpi_scan_lock);
+static int acpi_scan_device_check(struct acpi_device *adev)
+{
+ int error;
- if (ost_src == ACPI_NOTIFY_EJECT_REQUEST)
- acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
- ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+ acpi_bus_get_status(adev);
+ if (adev->status.present || adev->status.functional) {
+ /*
+ * This function is only called for device objects for which
+ * matching scan handlers exist. The only situation in which
+ * the scan handler is not attached to this device object yet
+ * is when the device has just appeared (either it wasn't
+ * present at all before or it was removed and then added
+ * again).
+ */
+ if (adev->handler) {
+ dev_warn(&adev->dev, "Already enumerated\n");
+ return -EALREADY;
+ }
+ error = acpi_bus_scan(adev->handle);
+ if (error) {
+ dev_warn(&adev->dev, "Namespace scan failure\n");
+ return error;
+ }
+ if (!adev->handler) {
+ dev_warn(&adev->dev, "Enumeration failure\n");
+ error = -ENODEV;
+ }
+ } else {
+ error = acpi_scan_device_not_present(adev);
+ }
+ return error;
+}
- if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
- kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
+static int acpi_scan_bus_check(struct acpi_device *adev)
+{
+ struct acpi_scan_handler *handler = adev->handler;
+ struct acpi_device *child;
+ int error;
- error = acpi_scan_hot_remove(device);
- if (error == -EPERM) {
- goto err_support;
- } else if (error) {
- goto err_out;
+ acpi_bus_get_status(adev);
+ if (!(adev->status.present || adev->status.functional)) {
+ acpi_scan_device_not_present(adev);
+ return 0;
}
+ if (handler && handler->hotplug.scan_dependent)
+ return handler->hotplug.scan_dependent(adev);
- out:
- mutex_unlock(&acpi_scan_lock);
- unlock_device_hotplug();
- return;
-
- err_support:
- ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
- err_out:
- acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL);
- goto out;
+ error = acpi_bus_scan(adev->handle);
+ if (error) {
+ dev_warn(&adev->dev, "Namespace scan failure\n");
+ return error;
+ }
+ list_for_each_entry(child, &adev->children, node) {
+ error = acpi_scan_bus_check(child);
+ if (error)
+ return error;
+ }
+ return 0;
}
-static void acpi_scan_bus_device_check(void *data, u32 ost_source)
+static void acpi_device_hotplug(void *data, u32 src)
{
- acpi_handle handle = data;
- struct acpi_device *device = NULL;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+ struct acpi_device *adev = data;
int error;
lock_device_hotplug();
mutex_lock(&acpi_scan_lock);
- if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
- acpi_bus_get_device(handle, &device);
- if (device) {
- dev_warn(&device->dev, "Attempt to re-insert\n");
- goto out;
- }
- }
- error = acpi_bus_scan(handle);
- if (error) {
- acpi_handle_warn(handle, "Namespace scan failure\n");
- goto out;
- }
- error = acpi_bus_get_device(handle, &device);
- if (error) {
- acpi_handle_warn(handle, "Missing device node object\n");
+ /*
+ * The device object's ACPI handle cannot become invalid as long as we
+ * are holding acpi_scan_lock, but it may have become invalid before
+ * that lock was acquired.
+ */
+ if (adev->handle == INVALID_ACPI_HANDLE)
goto out;
- }
- ost_code = ACPI_OST_SC_SUCCESS;
- if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
- kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
- out:
- acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
- mutex_unlock(&acpi_scan_lock);
- unlock_device_hotplug();
-}
-
-static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
-{
- u32 ost_status;
-
- switch (type) {
+ switch (src) {
case ACPI_NOTIFY_BUS_CHECK:
- acpi_handle_debug(handle,
- "ACPI_NOTIFY_BUS_CHECK event: unsupported\n");
- ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+ error = acpi_scan_bus_check(adev);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
- acpi_handle_debug(handle,
- "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n");
- ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+ error = acpi_scan_device_check(adev);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
- acpi_handle_debug(handle,
- "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n");
- ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+ case ACPI_OST_EC_OSPM_EJECT:
+ error = acpi_scan_hot_remove(adev);
break;
default:
- /* non-hotplug event; possibly handled by other handler */
- return;
+ error = -EINVAL;
+ break;
}
+ if (!error)
+ ost_code = ACPI_OST_SC_SUCCESS;
- acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
+ out:
+ acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+ put_device(&adev->dev);
+ mutex_unlock(&acpi_scan_lock);
+ unlock_device_hotplug();
}
static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
{
+ u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
struct acpi_scan_handler *handler = data;
struct acpi_device *adev;
acpi_status status;
- if (!handler->hotplug.enabled)
- return acpi_hotplug_unsupported(handle, type);
+ if (acpi_bus_get_device(handle, &adev))
+ goto err_out;
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
@@ -404,27 +500,27 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
break;
case ACPI_NOTIFY_EJECT_REQUEST:
acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
- if (acpi_bus_get_device(handle, &adev))
+ if (!handler->hotplug.enabled) {
+ acpi_handle_err(handle, "Eject disabled\n");
+ ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
goto err_out;
-
- get_device(&adev->dev);
- status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type);
- if (ACPI_SUCCESS(status))
- return;
-
- put_device(&adev->dev);
- goto err_out;
+ }
+ acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+ ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+ break;
default:
/* non-hotplug event; possibly handled by other handler */
return;
}
- status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type);
+ get_device(&adev->dev);
+ status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
if (ACPI_SUCCESS(status))
return;
+ put_device(&adev->dev);
+
err_out:
- acpi_evaluate_hotplug_ost(handle, type,
- ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
+ acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
}
static ssize_t real_power_state_show(struct device *dev,
@@ -475,7 +571,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
get_device(&acpi_device->dev);
- status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device,
+ status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
ACPI_OST_EC_OSPM_EJECT);
if (ACPI_SUCCESS(status))
return count;
@@ -567,6 +663,20 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ acpi_status status;
+ unsigned long long sta;
+
+ status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return sprintf(buf, "%llu\n", sta);
+}
+static DEVICE_ATTR_RO(status);
+
static int acpi_device_setup_files(struct acpi_device *dev)
{
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -622,6 +732,12 @@ static int acpi_device_setup_files(struct acpi_device *dev)
dev->pnp.sun = (unsigned long)-1;
}
+ if (acpi_has_method(dev->handle, "_STA")) {
+ result = device_create_file(&dev->dev, &dev_attr_status);
+ if (result)
+ goto end;
+ }
+
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
* hot-removal function from userland.
@@ -677,6 +793,8 @@ static void acpi_device_remove_files(struct acpi_device *dev)
device_remove_file(&dev->dev, &dev_attr_adr);
device_remove_file(&dev->dev, &dev_attr_modalias);
device_remove_file(&dev->dev, &dev_attr_hid);
+ if (acpi_has_method(dev->handle, "_STA"))
+ device_remove_file(&dev->dev, &dev_attr_status);
if (dev->handle)
device_remove_file(&dev->dev, &dev_attr_path);
}
@@ -782,8 +900,8 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
return -ENOMEM;
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen);
- if (len >= (sizeof(env->buf) - env->buflen))
- return -ENOMEM;
+ if (len <= 0)
+ return len;
env->buflen += len;
return 0;
}
@@ -907,9 +1025,91 @@ struct bus_type acpi_bus_type = {
.uevent = acpi_device_uevent,
};
-static void acpi_bus_data_handler(acpi_handle handle, void *context)
+static void acpi_device_del(struct acpi_device *device)
+{
+ mutex_lock(&acpi_device_lock);
+ if (device->parent)
+ list_del(&device->node);
+
+ list_del(&device->wakeup_list);
+ mutex_unlock(&acpi_device_lock);
+
+ acpi_power_add_remove_device(device, false);
+ acpi_device_remove_files(device);
+ if (device->remove)
+ device->remove(device);
+
+ device_del(&device->dev);
+}
+
+static LIST_HEAD(acpi_device_del_list);
+static DEFINE_MUTEX(acpi_device_del_lock);
+
+static void acpi_device_del_work_fn(struct work_struct *work_not_used)
+{
+ for (;;) {
+ struct acpi_device *adev;
+
+ mutex_lock(&acpi_device_del_lock);
+
+ if (list_empty(&acpi_device_del_list)) {
+ mutex_unlock(&acpi_device_del_lock);
+ break;
+ }
+ adev = list_first_entry(&acpi_device_del_list,
+ struct acpi_device, del_list);
+ list_del(&adev->del_list);
+
+ mutex_unlock(&acpi_device_del_lock);
+
+ acpi_device_del(adev);
+ /*
+ * Drop references to all power resources that might have been
+ * used by the device.
+ */
+ acpi_power_transition(adev, ACPI_STATE_D3_COLD);
+ put_device(&adev->dev);
+ }
+}
+
+/**
+ * acpi_scan_drop_device - Drop an ACPI device object.
+ * @handle: Handle of an ACPI namespace node, not used.
+ * @context: Address of the ACPI device object to drop.
+ *
+ * This is invoked by acpi_ns_delete_node() during the removal of the ACPI
+ * namespace node the device object pointed to by @context is attached to.
+ *
+ * The unregistration is carried out asynchronously to avoid running
+ * acpi_device_del() under the ACPICA's namespace mutex and the list is used to
+ * ensure the correct ordering (the device objects must be unregistered in the
+ * same order in which the corresponding namespace nodes are deleted).
+ */
+static void acpi_scan_drop_device(acpi_handle handle, void *context)
{
- /* Intentionally empty. */
+ static DECLARE_WORK(work, acpi_device_del_work_fn);
+ struct acpi_device *adev = context;
+
+ mutex_lock(&acpi_device_del_lock);
+
+ /*
+ * Use the ACPI hotplug workqueue which is ordered, so this work item
+ * won't run after any hotplug work items submitted subsequently. That
+ * prevents attempts to register device objects identical to those being
+ * deleted from happening concurrently (such attempts result from
+ * hotplug events handled via the ACPI hotplug workqueue). It also will
+ * run after all of the work items submitted previosuly, which helps
+ * those work items to ensure that they are not accessing stale device
+ * objects.
+ */
+ if (list_empty(&acpi_device_del_list))
+ acpi_queue_hotplug_work(&work);
+
+ list_add_tail(&adev->del_list, &acpi_device_del_list);
+ /* Make acpi_ns_validate_handle() return NULL for this handle. */
+ adev->handle = INVALID_ACPI_HANDLE;
+
+ mutex_unlock(&acpi_device_del_lock);
}
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
@@ -919,7 +1119,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
if (!device)
return -EINVAL;
- status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
+ status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
handle));
@@ -939,7 +1139,7 @@ int acpi_device_add(struct acpi_device *device,
if (device->handle) {
acpi_status status;
- status = acpi_attach_data(device->handle, acpi_bus_data_handler,
+ status = acpi_attach_data(device->handle, acpi_scan_drop_device,
device);
if (ACPI_FAILURE(status)) {
acpi_handle_err(device->handle,
@@ -957,6 +1157,7 @@ int acpi_device_add(struct acpi_device *device,
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->wakeup_list);
INIT_LIST_HEAD(&device->physical_node_list);
+ INIT_LIST_HEAD(&device->del_list);
mutex_init(&device->physical_node_lock);
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
@@ -1020,37 +1221,10 @@ int acpi_device_add(struct acpi_device *device,
mutex_unlock(&acpi_device_lock);
err_detach:
- acpi_detach_data(device->handle, acpi_bus_data_handler);
+ acpi_detach_data(device->handle, acpi_scan_drop_device);
return result;
}
-static void acpi_device_unregister(struct acpi_device *device)
-{
- mutex_lock(&acpi_device_lock);
- if (device->parent)
- list_del(&device->node);
-
- list_del(&device->wakeup_list);
- mutex_unlock(&acpi_device_lock);
-
- acpi_detach_data(device->handle, acpi_bus_data_handler);
-
- acpi_power_add_remove_device(device, false);
- acpi_device_remove_files(device);
- if (device->remove)
- device->remove(device);
-
- device_del(&device->dev);
- /*
- * Transition the device to D3cold to drop the reference counts of all
- * power resources the device depends on and turn off the ones that have
- * no more references.
- */
- acpi_device_set_power(device, ACPI_STATE_D3_COLD);
- device->handle = NULL;
- put_device(&device->dev);
-}
-
/* --------------------------------------------------------------------------
Driver Management
-------------------------------------------------------------------------- */
@@ -1624,11 +1798,13 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
device->device_type = type;
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
- STRUCT_TO_INT(device->status) = sta;
+ acpi_set_device_status(device, sta);
acpi_device_get_busid(device);
acpi_set_pnp_ids(handle, &device->pnp, type);
acpi_bus_get_flags(device);
device->flags.match_driver = false;
+ device->flags.initialized = true;
+ device->flags.visited = false;
device_initialize(&device->dev);
dev_set_uevent_suppress(&device->dev, true);
}
@@ -1713,6 +1889,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
return 0;
}
+bool acpi_device_is_present(struct acpi_device *adev)
+{
+ if (adev->status.present || adev->status.functional)
+ return true;
+
+ adev->flags.initialized = false;
+ return false;
+}
+
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
char *idstr,
const struct acpi_device_id **matchid)
@@ -1772,7 +1957,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
*/
list_for_each_entry(hwid, &pnp.ids, list) {
handler = acpi_scan_match_handler(hwid->id, NULL);
- if (handler && !handler->hotplug.ignore) {
+ if (handler) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
acpi_hotplug_notify_cb, handler);
break;
@@ -1806,18 +1991,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
acpi_scan_init_hotplug(handle, type);
- if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
- !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
- struct acpi_device_wakeup wakeup;
-
- if (acpi_has_method(handle, "_PRW")) {
- acpi_bus_extract_wakeup_device_power_package(handle,
- &wakeup);
- acpi_power_resources_list_free(&wakeup.resources);
- }
- return AE_CTRL_DEPTH;
- }
-
acpi_add_single_object(&device, handle, type, sta);
if (!device)
return AE_CTRL_DEPTH;
@@ -1852,36 +2025,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
return ret;
}
-static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
- void *not_used, void **ret_not_used)
+static void acpi_bus_attach(struct acpi_device *device)
{
- struct acpi_device *device;
- unsigned long long sta_not_used;
+ struct acpi_device *child;
int ret;
- /*
- * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
- * namespace walks prematurely.
- */
- if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
- return AE_OK;
-
- if (acpi_bus_get_device(handle, &device))
- return AE_CTRL_DEPTH;
-
+ acpi_bus_get_status(device);
+ /* Skip devices that are not present. */
+ if (!acpi_device_is_present(device)) {
+ device->flags.visited = false;
+ return;
+ }
if (device->handler)
- return AE_OK;
+ goto ok;
+ if (!device->flags.initialized) {
+ acpi_bus_update_power(device, NULL);
+ device->flags.initialized = true;
+ }
+ device->flags.visited = false;
ret = acpi_scan_attach_handler(device);
if (ret < 0)
- return AE_CTRL_DEPTH;
+ return;
device->flags.match_driver = true;
- if (ret > 0)
- return AE_OK;
+ if (!ret) {
+ ret = device_attach(&device->dev);
+ if (ret < 0)
+ return;
+ }
+ device->flags.visited = true;
- ret = device_attach(&device->dev);
- return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
+ ok:
+ list_for_each_entry(child, &device->children, node)
+ acpi_bus_attach(child);
}
/**
@@ -1901,75 +2078,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
int acpi_bus_scan(acpi_handle handle)
{
void *device = NULL;
- int error = 0;
if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_check_add, NULL, NULL, &device);
- if (!device)
- error = -ENODEV;
- else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL)))
- acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
- acpi_bus_device_attach, NULL, NULL, NULL);
-
- return error;
-}
-EXPORT_SYMBOL(acpi_bus_scan);
-
-static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
- void *not_used, void **ret_not_used)
-{
- struct acpi_device *device = NULL;
-
- if (!acpi_bus_get_device(handle, &device)) {
- struct acpi_scan_handler *dev_handler = device->handler;
-
- if (dev_handler) {
- if (dev_handler->detach)
- dev_handler->detach(device);
-
- device->handler = NULL;
- } else {
- device_release_driver(&device->dev);
- }
+ if (device) {
+ acpi_bus_attach(device);
+ return 0;
}
- return AE_OK;
-}
-
-static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
- void *not_used, void **ret_not_used)
-{
- struct acpi_device *device = NULL;
-
- if (!acpi_bus_get_device(handle, &device))
- acpi_device_unregister(device);
-
- return AE_OK;
+ return -ENODEV;
}
+EXPORT_SYMBOL(acpi_bus_scan);
/**
- * acpi_bus_trim - Remove ACPI device node and all of its descendants
- * @start: Root of the ACPI device nodes subtree to remove.
+ * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
+ * @adev: Root of the ACPI namespace scope to walk.
*
* Must be called under acpi_scan_lock.
*/
-void acpi_bus_trim(struct acpi_device *start)
+void acpi_bus_trim(struct acpi_device *adev)
{
+ struct acpi_scan_handler *handler = adev->handler;
+ struct acpi_device *child;
+
+ list_for_each_entry_reverse(child, &adev->children, node)
+ acpi_bus_trim(child);
+
+ if (handler) {
+ if (handler->detach)
+ handler->detach(adev);
+
+ adev->handler = NULL;
+ } else {
+ device_release_driver(&adev->dev);
+ }
/*
- * Execute acpi_bus_device_detach() as a post-order callback to detach
- * all ACPI drivers from the device nodes being removed.
- */
- acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
- acpi_bus_device_detach, NULL, NULL);
- acpi_bus_device_detach(start->handle, 0, NULL, NULL);
- /*
- * Execute acpi_bus_remove() as a post-order callback to remove device
- * nodes in the given namespace scope.
+ * Most likely, the device is going away, so put it into D3cold before
+ * that.
*/
- acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
- acpi_bus_remove, NULL, NULL);
- acpi_bus_remove(start->handle, 0, NULL, NULL);
+ acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
+ adev->flags.initialized = false;
+ adev->flags.visited = false;
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
@@ -2047,14 +2197,14 @@ int __init acpi_scan_init(void)
result = acpi_bus_scan_fixed();
if (result) {
- acpi_device_unregister(acpi_root);
+ acpi_detach_data(acpi_root->handle, acpi_scan_drop_device);
+ acpi_device_del(acpi_root);
+ put_device(&acpi_root->dev);
goto out;
}
acpi_update_all_gpes();
- acpi_pci_root_hp_init();
-
out:
mutex_unlock(&acpi_scan_lock);
return result;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 721e949e606e..b718806657cd 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -18,12 +18,8 @@
#include <linux/reboot.h>
#include <linux/acpi.h>
#include <linux/module.h>
-
#include <asm/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
#include "internal.h"
#include "sleep.h"
@@ -670,11 +666,8 @@ static void acpi_hibernation_leave(void)
/* Reprogram control registers */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
/* Check the hardware signature */
- if (facs && s4_hardware_signature != facs->hardware_signature) {
- printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
- "cannot resume!\n");
- panic("ACPI S4 hardware signature mismatch");
- }
+ if (facs && s4_hardware_signature != facs->hardware_signature)
+ pr_crit("ACPI: Hardware changed while hibernated, success doubtful!\n");
/* Restore the NVS memory area */
suspend_nvs_restore();
/* Allow EC transactions to happen. */
@@ -806,9 +799,6 @@ int __init acpi_sleep_init(void)
char *pos = supported;
int i;
- if (acpi_disabled)
- return 0;
-
acpi_sleep_dmi_check();
sleep_states[ACPI_STATE_S0] = 1;
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 6dbc3ca45223..443dc9366052 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -5,7 +5,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include "internal.h"
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index d67a1fe07f0e..5837f857ac2e 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -278,12 +278,13 @@ acpi_table_parse_madt(enum acpi_madt_type id,
/**
* acpi_table_parse - find table with @id, run @handler on it
- *
* @id: table id to find
* @handler: handler to run
*
* Scan the ACPI System Descriptor Table (STD) for a table matching @id,
- * run @handler on it. Return 0 if table found, return on if not.
+ * run @handler on it.
+ *
+ * Return 0 if table found, -errno if not.
*/
int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
{
@@ -293,7 +294,7 @@ int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
if (acpi_disabled)
return -ENODEV;
- if (!handler)
+ if (!id || !handler)
return -EINVAL;
if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
@@ -306,7 +307,7 @@ int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
early_acpi_os_unmap_memory(table, tbl_size);
return 0;
} else
- return 1;
+ return -ENODEV;
}
/*
@@ -351,7 +352,7 @@ int __init acpi_table_init(void)
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
if (ACPI_FAILURE(status))
- return 1;
+ return -EINVAL;
check_multiple_madt();
return 0;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 0d9f46b5ae6d..8349a555b92b 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -41,10 +41,9 @@
#include <linux/kmod.h>
#include <linux/reboot.h>
#include <linux/device.h>
-#include <asm/uaccess.h>
#include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
+#include <asm/uaccess.h>
#define PREFIX "ACPI: "
@@ -862,7 +861,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
return acpi_thermal_cooling_device_cb(thermal, cdev, false);
}
-static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
.bind = acpi_thermal_bind_cooling_device,
.unbind = acpi_thermal_unbind_cooling_device,
.get_temp = thermal_get_temp,
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 6d408bfbbb1d..0347a37eb438 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -30,8 +30,6 @@
#include <linux/types.h>
#include <linux/hardirq.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#include "internal.h"
@@ -574,3 +572,100 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
return status;
}
+
+/**
+ * acpi_evaluate_dsm - evaluate device's _DSM method
+ * @handle: ACPI device handle
+ * @uuid: UUID of requested functions, should be 16 bytes
+ * @rev: revision number of requested function
+ * @func: requested function number
+ * @argv4: the function specific parameter
+ *
+ * Evaluate device's _DSM method with specified UUID, revision id and
+ * function number. Caller needs to free the returned object.
+ *
+ * Though ACPI defines the fourth parameter for _DSM should be a package,
+ * some old BIOSes do expect a buffer or an integer etc.
+ */
+union acpi_object *
+acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func,
+ union acpi_object *argv4)
+{
+ acpi_status ret;
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object params[4];
+ struct acpi_object_list input = {
+ .count = 4,
+ .pointer = params,
+ };
+
+ params[0].type = ACPI_TYPE_BUFFER;
+ params[0].buffer.length = 16;
+ params[0].buffer.pointer = (char *)uuid;
+ params[1].type = ACPI_TYPE_INTEGER;
+ params[1].integer.value = rev;
+ params[2].type = ACPI_TYPE_INTEGER;
+ params[2].integer.value = func;
+ if (argv4) {
+ params[3] = *argv4;
+ } else {
+ params[3].type = ACPI_TYPE_PACKAGE;
+ params[3].package.count = 0;
+ params[3].package.elements = NULL;
+ }
+
+ ret = acpi_evaluate_object(handle, "_DSM", &input, &buf);
+ if (ACPI_SUCCESS(ret))
+ return (union acpi_object *)buf.pointer;
+
+ if (ret != AE_NOT_FOUND)
+ acpi_handle_warn(handle,
+ "failed to evaluate _DSM (0x%x)\n", ret);
+
+ return NULL;
+}
+EXPORT_SYMBOL(acpi_evaluate_dsm);
+
+/**
+ * acpi_check_dsm - check if _DSM method supports requested functions.
+ * @handle: ACPI device handle
+ * @uuid: UUID of requested functions, should be 16 bytes at least
+ * @rev: revision number of requested functions
+ * @funcs: bitmap of requested functions
+ * @exclude: excluding special value, used to support i915 and nouveau
+ *
+ * Evaluate device's _DSM method to check whether it supports requested
+ * functions. Currently only support 64 functions at maximum, should be
+ * enough for now.
+ */
+bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
+{
+ int i;
+ u64 mask = 0;
+ union acpi_object *obj;
+
+ if (funcs == 0)
+ return false;
+
+ obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL);
+ if (!obj)
+ return false;
+
+ /* For compatibility, old BIOSes may return an integer */
+ if (obj->type == ACPI_TYPE_INTEGER)
+ mask = obj->integer.value;
+ else if (obj->type == ACPI_TYPE_BUFFER)
+ for (i = 0; i < obj->buffer.length && i < 8; i++)
+ mask |= (((u8)obj->buffer.pointer[i]) << (i * 8));
+ ACPI_FREE(obj);
+
+ /*
+ * Bit 0 indicates whether there's support for any functions other than
+ * function 0 for the specified UUID and revision.
+ */
+ if ((mask & 0x1) && (mask & funcs) == funcs)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(acpi_check_dsm);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 995e91bcb97b..b727d105046d 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -37,12 +37,11 @@
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
-#include <asm/uaccess.h>
#include <linux/dmi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#include <linux/suspend.h>
+#include <linux/acpi.h>
#include <acpi/video.h>
+#include <asm/uaccess.h>
#include "internal.h"
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 84875fd4c74f..f0447d3daf2c 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -50,7 +50,7 @@ static bool acpi_video_caps_checked;
static acpi_status
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
- void **retyurn_value)
+ void **return_value)
{
long *cap = context;
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index 7bfbe40bc43b..1638401ab282 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -5,7 +5,6 @@
#include <linux/init.h>
#include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
#include <linux/kernel.h>
#include <linux/types.h>
OpenPOWER on IntegriCloud