diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 23:48:54 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 23:48:54 +0400 |
commit | 4dedde7c7a18f55180574f934dbc1be84ca0400b (patch) | |
tree | d7cc511e8ba8ffceadf3f45b9a63395c4e4183c5 /drivers | |
parent | 683b6c6f82a60fabf47012581c2cfbf1b037ab95 (diff) | |
parent | 0ecfe310f4517d7505599be738158087c165be7c (diff) | |
download | linux-4dedde7c7a18f55180574f934dbc1be84ca0400b.tar.xz |
Merge tag 'pm+acpi-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management updates from Rafael Wysocki:
"The majority of this material spent some time in linux-next, some of
it even several weeks. There are a few relatively fresh commits in
it, but they are mostly fixes and simple cleanups.
ACPI took the lead this time, both in terms of the number of commits
and the number of modified lines of code, cpufreq follows and there
are a few changes in the PM core and in cpuidle too.
A new feature that already got some LWN.net's attention is the device
PM QoS extension allowing latency tolerance requirements to be
propagated from leaf devices to their ancestors with hardware
interfaces for specifying latency tolerance. That should help systems
with hardware-driven power management to avoid going too far with it
in cases when there are latency tolerance constraints.
There also are some significant changes in the ACPI core related to
the way in which hotplug notifications are handled. They affect PCI
hotplug (ACPIPHP) and the ACPI dock station code too. The bottom line
is that all those notification now go through the root notify handler
and are propagated to the interested subsystems by means of callbacks
instead of having to install a notify handler for each device object
that we can potentially get hotplug notifications for.
In addition to that ACPICA will now advertise "Windows 2013"
compatibility for _OSI, because some systems out there don't work
correctly if that is not done (some of them don't even boot).
On the system suspend side of things, all of the device suspend and
resume callbacks, except for ->prepare() and ->complete(), are now
going to be executed asynchronously as that turns out to speed up
system suspend and resume on some platforms quite significantly and we
have a few more optimizations in that area.
Apart from that, there are some new device IDs and fixes and cleanups
all over. In particular, the system suspend and resume handling by
cpufreq should be improved and the cpuidle menu governor should be a
bit more robust now.
Specifics:
- Device PM QoS support for latency tolerance constraints on systems
with hardware interfaces allowing such constraints to be specified.
That is necessary to prevent hardware-driven power management from
becoming overly aggressive on some systems and to prevent power
management features leading to excessive latencies from being used
in some cases.
- Consolidation of the handling of ACPI hotplug notifications for
device objects. This causes all device hotplug notifications to go
through the root notify handler (that was executed for all of them
anyway before) that propagates them to individual subsystems, if
necessary, by executing callbacks provided by those subsystems
(those callbacks are associated with struct acpi_device objects
during device enumeration). As a result, the code in question
becomes both smaller in size and more straightforward and all of
those changes should not affect users.
- ACPICA update, including fixes related to the handling of _PRT in
cases when it is broken and the addition of "Windows 2013" to the
list of supported "features" for _OSI (which is necessary to
support systems that work incorrectly or don't even boot without
it). Changes from Bob Moore and Lv Zheng.
- Consolidation of ACPI _OST handling from Jiang Liu.
- ACPI battery and AC fixes allowing unusual system configurations to
be handled by that code from Alexander Mezin.
- New device IDs for the ACPI LPSS driver from Chiau Ee Chew.
- ACPI fan and thermal optimizations related to system suspend and
resume from Aaron Lu.
- Cleanups related to ACPI video from Jean Delvare.
- Assorted ACPI fixes and cleanups from Al Stone, Hanjun Guo, Lan
Tianyu, Paul Bolle, Tomasz Nowicki.
- Intel RAPL (Running Average Power Limits) driver cleanups from
Jacob Pan.
- intel_pstate fixes and cleanups from Dirk Brandewie.
- cpufreq fixes related to system suspend/resume handling from Viresh
Kumar.
- cpufreq core fixes and cleanups from Viresh Kumar, Stratos
Karafotis, Saravana Kannan, Rashika Kheria, Joe Perches.
- cpufreq drivers updates from Viresh Kumar, Zhuoyu Zhang, Rob
Herring.
- cpuidle fixes related to the menu governor from Tuukka Tikkanen.
- cpuidle fix related to coupled CPUs handling from Paul Burton.
- Asynchronous execution of all device suspend and resume callbacks,
except for ->prepare and ->complete, during system suspend and
resume from Chuansheng Liu.
- Delayed resuming of runtime-suspended devices during system suspend
for the PCI bus type and ACPI PM domain.
- New set of PM helper routines to allow device runtime PM callbacks
to be used during system suspend and resume more easily from Ulf
Hansson.
- Assorted fixes and cleanups in the PM core from Geert Uytterhoeven,
Prabhakar Lad, Philipp Zabel, Rashika Kheria, Sebastian Capella.
- devfreq fix from Saravana Kannan"
* tag 'pm+acpi-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (162 commits)
PM / devfreq: Rewrite devfreq_update_status() to fix multiple bugs
PM / sleep: Correct whitespace errors in <linux/pm.h>
intel_pstate: Set core to min P state during core offline
cpufreq: Add stop CPU callback to cpufreq_driver interface
cpufreq: Remove unnecessary braces
cpufreq: Fix checkpatch errors and warnings
cpufreq: powerpc: add cpufreq transition latency for FSL e500mc SoCs
MAINTAINERS: Reorder maintainer addresses for PM and ACPI
PM / Runtime: Update runtime_idle() documentation for return value meaning
video / output: Drop display output class support
fujitsu-laptop: Drop unneeded include
acer-wmi: Stop selecting VIDEO_OUTPUT_CONTROL
ACPI / gpu / drm: Stop selecting VIDEO_OUTPUT_CONTROL
ACPI / video: fix ACPI_VIDEO dependencies
cpufreq: remove unused notifier: CPUFREQ_{SUSPENDCHANGE|RESUMECHANGE}
cpufreq: Do not allow ->setpolicy drivers to provide ->target
cpufreq: arm_big_little: set 'physical_cluster' for each CPU
cpufreq: arm_big_little: make vexpress driver depend on bL core driver
ACPI / button: Add ACPI Button event via netlink routine
ACPI: Remove duplicate definitions of PREFIX
...
Diffstat (limited to 'drivers')
273 files changed, 2772 insertions, 2493 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4770de5707b9..c205653e9644 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -43,19 +43,6 @@ config ACPI_SLEEP depends on SUSPEND || HIBERNATION default y -config ACPI_PROCFS - bool "Deprecated /proc/acpi files" - depends on PROC_FS - help - For backwards compatibility, this option allows - deprecated /proc/acpi/ files to exist, even when - they have been replaced by functions in /sys. - - This option has no effect on /proc/acpi/ files - and functions which do not yet exist in /sys. - - Say N to delete /proc/acpi/ files that have moved to /sys/ - config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" default n @@ -115,7 +102,7 @@ config ACPI_BUTTON config ACPI_VIDEO tristate "Video" - depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL + depends on X86 && BACKLIGHT_CLASS_DEVICE depends on INPUT select THERMAL help @@ -343,6 +330,19 @@ config ACPI_BGRT data from the firmware boot splash. It will appear under /sys/firmware/acpi/bgrt/ . +config ACPI_REDUCED_HARDWARE_ONLY + bool "Hardware-reduced ACPI support only" if EXPERT + def_bool n + depends on ACPI + help + This config item changes the way the ACPI code is built. When this + option is selected, the kernel will use a specialized version of + ACPICA that ONLY supports the ACPI "reduced hardware" mode. The + resulting kernel will be smaller but it will also be restricted to + running in ACPI reduced hardware mode ONLY. + + If you are unsure what to do, do not enable this option. + source "drivers/acpi/apei/Kconfig" config ACPI_EXTLOG diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 6f190bc2b8b7..2c01c1da29ce 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -33,6 +33,7 @@ #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/acpi.h> +#include "battery.h" #define PREFIX "ACPI: " @@ -57,6 +58,7 @@ struct acpi_ac { struct power_supply charger; struct platform_device *pdev; unsigned long long state; + struct notifier_block battery_nb; }; #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) @@ -152,6 +154,26 @@ static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) return; } +static int acpi_ac_battery_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct acpi_ac *ac = container_of(nb, struct acpi_ac, battery_nb); + struct acpi_bus_event *event = (struct acpi_bus_event *)data; + + /* + * On HP Pavilion dv6-6179er AC status notifications aren't triggered + * when adapter is plugged/unplugged. However, battery status + * notifcations are triggered when battery starts charging or + * discharging. Re-reading AC status triggers lost AC notifications, + * if AC status has changed. + */ + if (strcmp(event->device_class, ACPI_BATTERY_CLASS) == 0 && + event->type == ACPI_BATTERY_NOTIFY_STATUS) + acpi_ac_get_state(ac); + + return NOTIFY_OK; +} + static int thinkpad_e530_quirk(const struct dmi_system_id *d) { ac_sleep_before_get_state_ms = 1000; @@ -215,6 +237,8 @@ static int acpi_ac_probe(struct platform_device *pdev) acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); + ac->battery_nb.notifier_call = acpi_ac_battery_notify; + register_acpi_notifier(&ac->battery_nb); end: if (result) kfree(ac); @@ -261,6 +285,7 @@ static int acpi_ac_remove(struct platform_device *pdev) ac = platform_get_drvdata(pdev); if (ac->charger.dev) power_supply_unregister(&ac->charger); + unregister_acpi_notifier(&ac->battery_nb); kfree(ac); diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c index 84190ed89c04..961b45d18a5d 100644 --- a/drivers/acpi/acpi_cmos_rtc.c +++ b/drivers/acpi/acpi_cmos_rtc.c @@ -18,8 +18,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - ACPI_MODULE_NAME("cmos rtc"); static const struct acpi_device_id acpi_cmos_rtc_ids[] = { diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 6745fe137b9e..69e29f409d4c 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -33,6 +33,13 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_GENERAL_UART_RTS_OVRD BIT(3) #define LPSS_SW_LTR 0x10 #define LPSS_AUTO_LTR 0x14 +#define LPSS_LTR_SNOOP_REQ BIT(15) +#define LPSS_LTR_SNOOP_MASK 0x0000FFFF +#define LPSS_LTR_SNOOP_LAT_1US 0x800 +#define LPSS_LTR_SNOOP_LAT_32US 0xC00 +#define LPSS_LTR_SNOOP_LAT_SHIFT 5 +#define LPSS_LTR_SNOOP_LAT_CUTOFF 3000 +#define LPSS_LTR_MAX_VAL 0x3FF #define LPSS_TX_INT 0x20 #define LPSS_TX_INT_MASK BIT(1) @@ -102,6 +109,16 @@ static struct lpss_device_desc lpt_sdio_dev_desc = { .ltr_required = true, }; +static struct lpss_shared_clock pwm_clock = { + .name = "pwm_clk", + .rate = 25000000, +}; + +static struct lpss_device_desc byt_pwm_dev_desc = { + .clk_required = true, + .shared_clock = &pwm_clock, +}; + static struct lpss_shared_clock uart_clock = { .name = "uart_clk", .rate = 44236800, @@ -157,6 +174,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33C7", }, /* BayTrail LPSS devices */ + { "80860F09", (unsigned long)&byt_pwm_dev_desc }, { "80860F0A", (unsigned long)&byt_uart_dev_desc }, { "80860F0E", (unsigned long)&byt_spi_dev_desc }, { "80860F14", (unsigned long)&byt_sdio_dev_desc }, @@ -315,6 +333,17 @@ static int acpi_lpss_create_device(struct acpi_device *adev, return ret; } +static u32 __lpss_reg_read(struct lpss_private_data *pdata, unsigned int reg) +{ + return readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg); +} + +static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata, + unsigned int reg) +{ + writel(val, pdata->mmio_base + pdata->dev_desc->prv_offset + reg); +} + static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) { struct acpi_device *adev; @@ -336,7 +365,7 @@ static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) ret = -ENODEV; goto out; } - *val = readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg); + *val = __lpss_reg_read(pdata, reg); out: spin_unlock_irqrestore(&dev->power.lock, flags); @@ -389,6 +418,37 @@ static struct attribute_group lpss_attr_group = { .name = "lpss_ltr", }; +static void acpi_lpss_set_ltr(struct device *dev, s32 val) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + u32 ltr_mode, ltr_val; + + ltr_mode = __lpss_reg_read(pdata, LPSS_GENERAL); + if (val < 0) { + if (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) { + ltr_mode &= ~LPSS_GENERAL_LTR_MODE_SW; + __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); + } + return; + } + ltr_val = __lpss_reg_read(pdata, LPSS_SW_LTR) & ~LPSS_LTR_SNOOP_MASK; + if (val >= LPSS_LTR_SNOOP_LAT_CUTOFF) { + ltr_val |= LPSS_LTR_SNOOP_LAT_32US; + val = LPSS_LTR_MAX_VAL; + } else if (val > LPSS_LTR_MAX_VAL) { + ltr_val |= LPSS_LTR_SNOOP_LAT_32US | LPSS_LTR_SNOOP_REQ; + val >>= LPSS_LTR_SNOOP_LAT_SHIFT; + } else { + ltr_val |= LPSS_LTR_SNOOP_LAT_1US | LPSS_LTR_SNOOP_REQ; + } + ltr_val |= val; + __lpss_reg_write(ltr_val, pdata, LPSS_SW_LTR); + if (!(ltr_mode & LPSS_GENERAL_LTR_MODE_SW)) { + ltr_mode |= LPSS_GENERAL_LTR_MODE_SW; + __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); + } +} + static int acpi_lpss_platform_notify(struct notifier_block *nb, unsigned long action, void *data) { @@ -426,9 +486,29 @@ static struct notifier_block acpi_lpss_nb = { .notifier_call = acpi_lpss_platform_notify, }; +static void acpi_lpss_bind(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required) + return; + + if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) + dev->power.set_latency_tolerance = acpi_lpss_set_ltr; + else + dev_err(dev, "MMIO size insufficient to access LTR\n"); +} + +static void acpi_lpss_unbind(struct device *dev) +{ + dev->power.set_latency_tolerance = NULL; +} + static struct acpi_scan_handler lpss_handler = { .ids = acpi_lpss_device_ids, .attach = acpi_lpss_create_device, + .bind = acpi_lpss_bind, + .unbind = acpi_lpss_unbind, }; void __init acpi_lpss_init(void) diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index df96a0fe4890..37d73024b82e 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -408,28 +408,14 @@ static int acpi_pad_pur(acpi_handle handle) return num; } -/* Notify firmware how many CPUs are idle */ -static void acpi_pad_ost(acpi_handle handle, int stat, - uint32_t idle_cpus) -{ - union acpi_object params[3] = { - {.type = ACPI_TYPE_INTEGER,}, - {.type = ACPI_TYPE_INTEGER,}, - {.type = ACPI_TYPE_BUFFER,}, - }; - struct acpi_object_list arg_list = {3, params}; - - params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY; - params[1].integer.value = stat; - params[2].buffer.length = 4; - params[2].buffer.pointer = (void *)&idle_cpus; - acpi_evaluate_object(handle, "_OST", &arg_list, NULL); -} - static void acpi_pad_handle_notify(acpi_handle handle) { int num_cpus; uint32_t idle_cpus; + struct acpi_buffer param = { + .length = 4, + .pointer = (void *)&idle_cpus, + }; mutex_lock(&isolated_cpus_lock); num_cpus = acpi_pad_pur(handle); @@ -439,7 +425,7 @@ static void acpi_pad_handle_notify(acpi_handle handle) } acpi_pad_idle_cpus(num_cpus); idle_cpus = acpi_pad_idle_cpus_num(); - acpi_pad_ost(handle, 0, idle_cpus); + acpi_evaluate_ost(handle, ACPI_PROCESSOR_AGGREGATOR_NOTIFY, 0, ¶m); mutex_unlock(&isolated_cpus_lock); } diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 438304086ff1..b7ed86a20427 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -122,6 +122,8 @@ acpi-y += \ rsaddr.o \ rscalc.o \ rscreate.o \ + rsdump.o \ + rsdumpinfo.o \ rsinfo.o \ rsio.o \ rsirq.o \ @@ -132,8 +134,6 @@ acpi-y += \ rsutils.o \ rsxface.o -acpi-$(ACPI_FUTURE_USAGE) += rsdump.o rsdumpinfo.o - acpi-y += \ tbfadt.o \ tbfind.o \ diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index 8a6c4a0d22db..6f1c616910ac 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 2bf3ca2b8a7a..68a91eb0fa48 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -115,6 +115,8 @@ ACPI_HW_DEPENDENT_RETURN_VOID(void char *block_arg)) ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) +void acpi_db_execute_test(char *type_arg); + /* * dbconvert - miscellaneous conversion routines */ diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 427db72a6302..5b472c43c31d 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 0fb0adf435d6..68ec61fff188 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 4ed1aa384df2..8f40bb972ae3 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,11 +51,19 @@ * to simplify maintenance of the code. */ #ifdef DEFINE_ACPI_GLOBALS -#define ACPI_EXTERN -#define ACPI_INIT_GLOBAL(a,b) a=b +#define ACPI_GLOBAL(type,name) \ + extern type name; \ + type name + +#define ACPI_INIT_GLOBAL(type,name,value) \ + type name=value + #else -#define ACPI_EXTERN extern -#define ACPI_INIT_GLOBAL(a,b) a +#define ACPI_GLOBAL(type,name) \ + extern type name + +#define ACPI_INIT_GLOBAL(type,name,value) \ + extern type name #endif #ifdef DEFINE_ACPI_GLOBALS @@ -82,7 +90,7 @@ * 5) Allow unresolved references (invalid target name) in package objects * 6) Enable warning messages for behavior that is not ACPI spec compliant */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE); /* * Automatically serialize ALL control methods? Default is FALSE, meaning @@ -90,25 +98,25 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); * Only change this if the ASL code is poorly written and cannot handle * reentrancy even though methods are marked "NotSerialized". */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_all_methods_serialized, FALSE); /* * Create the predefined _OSI method in the namespace? Default is TRUE * because ACPI CA is fully compatible with other ACPI implementations. * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE); /* * Optionally use default values for the ACPI register widths. Set this to * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_use_default_register_widths, TRUE); /* * Optionally enable output from the AML Debug Object. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_aml_debug_object, FALSE); /* * Optionally copy the entire DSDT to local memory (instead of simply @@ -116,7 +124,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); * DSDT, creating the need for this option. Default is FALSE, do not copy * the DSDT. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE); /* * Optionally ignore an XSDT if present and use the RSDT instead. @@ -124,7 +132,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); * 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); +ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE); /* * Optionally use 32-bit FADT addresses if and when there is a conflict @@ -134,7 +142,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_do_not_use_xsdt, FALSE); * 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); +ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, FALSE); /* * Optionally truncate I/O addresses to 16 bits. Provides compatibility @@ -142,47 +150,28 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use32_bit_fadt_addresses, FALSE); * this value is set to TRUE if any Windows OSI strings have been * requested by the BIOS. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_truncate_io_addresses, FALSE); /* * Disable runtime checking and repair of values returned by control methods. * Use only if the repair is causing a problem on a particular machine. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE); /* * Optionally do not load any SSDTs from the RSDT/XSDT during initialization. * This can be useful for debugging ACPI problems on some machines. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_ssdt_table_load, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_load, FALSE); /* * We keep track of the latest version of Windows that has been requested by * the BIOS. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_osi_data, 0); - -/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ - -struct acpi_table_fadt acpi_gbl_FADT; -u32 acpi_current_gpe_count; -u32 acpi_gbl_trace_flags; -acpi_name acpi_gbl_trace_method_name; -u8 acpi_gbl_system_awake_and_running; - -/* - * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning - * that the ACPI hardware is no longer required. A flag in the FADT indicates - * a reduced HW machine, and that flag is duplicated here for convenience. - */ -u8 acpi_gbl_reduced_hardware; +ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0); #endif /* DEFINE_ACPI_GLOBALS */ -/* Do not disassemble buffers to resource descriptors */ - -ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE); - /***************************************************************************** * * ACPI Table globals @@ -190,37 +179,36 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE); ****************************************************************************/ /* - * acpi_gbl_root_table_list is the master list of ACPI tables that were - * found in the RSDT/XSDT. + * Master list of all ACPI tables that were found in the RSDT/XSDT. */ -ACPI_EXTERN struct acpi_table_list acpi_gbl_root_table_list; +ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); + +/* DSDT information. Used to check for DSDT corruption */ + +ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT); +ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); #if (!ACPI_REDUCED_HARDWARE) -ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; +ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS); #endif /* !ACPI_REDUCED_HARDWARE */ /* These addresses are calculated from the FADT Event Block addresses */ -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; - -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_status); +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_enable); -/* DSDT information. Used to check for DSDT corruption */ - -ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; -ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header; +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_status); +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_enable); /* - * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is + * Handle both ACPI 1.0 and ACPI 2.0+ Integer widths. The integer width is * determined by the revision of the DSDT: If the DSDT revision is less than * 2, use only the lower 32 bits of the internal 64-bit Integer. */ -ACPI_EXTERN u8 acpi_gbl_integer_bit_width; -ACPI_EXTERN u8 acpi_gbl_integer_byte_width; -ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; +ACPI_GLOBAL(u8, acpi_gbl_integer_bit_width); +ACPI_GLOBAL(u8, acpi_gbl_integer_byte_width); +ACPI_GLOBAL(u8, acpi_gbl_integer_nybble_width); /***************************************************************************** * @@ -233,36 +221,36 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. * (The table maps local handles to the real OS handles) */ -ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; +ACPI_GLOBAL(struct acpi_mutex_info, acpi_gbl_mutex_info[ACPI_NUM_MUTEX]); /* * Global lock mutex is an actual AML mutex object * Global lock semaphore works in conjunction with the actual global lock * Global lock spinlock is used for "pending" handshake */ -ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; -ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; -ACPI_EXTERN acpi_spinlock acpi_gbl_global_lock_pending_lock; -ACPI_EXTERN u16 acpi_gbl_global_lock_handle; -ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; -ACPI_EXTERN u8 acpi_gbl_global_lock_present; -ACPI_EXTERN u8 acpi_gbl_global_lock_pending; +ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_global_lock_mutex); +ACPI_GLOBAL(acpi_semaphore, acpi_gbl_global_lock_semaphore); +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_global_lock_pending_lock); +ACPI_GLOBAL(u16, acpi_gbl_global_lock_handle); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_acquired); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_present); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_pending); /* * Spinlocks are used for interfaces that can be possibly called at * interrupt level */ -ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */ -ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ -ACPI_EXTERN acpi_spinlock acpi_gbl_reference_count_lock; +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */ +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */ +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock); /* Mutex for _OSI support */ -ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; +ACPI_GLOBAL(acpi_mutex, acpi_gbl_osi_mutex); /* Reader/Writer lock is used for namespace walk and dynamic table unload */ -ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; +ACPI_GLOBAL(struct acpi_rw_lock, acpi_gbl_namespace_rw_lock); /***************************************************************************** * @@ -272,70 +260,69 @@ ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; /* Object caches */ -ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_state_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_ext_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_namespace_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_state_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_ext_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_operand_cache); + +/* System */ + +ACPI_INIT_GLOBAL(u32, acpi_gbl_startup_flags, 0); +ACPI_INIT_GLOBAL(u8, acpi_gbl_shutdown, TRUE); /* Global handlers */ -ACPI_EXTERN struct acpi_global_notify_handler acpi_gbl_global_notify[2]; -ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; -ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; -ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler; -ACPI_EXTERN void *acpi_gbl_table_handler_context; -ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; -ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; -ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list; +ACPI_GLOBAL(struct acpi_global_notify_handler, acpi_gbl_global_notify[2]); +ACPI_GLOBAL(acpi_exception_handler, acpi_gbl_exception_handler); +ACPI_GLOBAL(acpi_init_handler, acpi_gbl_init_handler); +ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler); +ACPI_GLOBAL(void *, acpi_gbl_table_handler_context); +ACPI_GLOBAL(struct acpi_walk_state *, acpi_gbl_breakpoint_walk); +ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler); +ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list); /* Owner ID support */ -ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; -ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; -ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; +ACPI_GLOBAL(u32, acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]); +ACPI_GLOBAL(u8, acpi_gbl_last_owner_id_index); +ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset); /* Initialization sequencing */ -ACPI_EXTERN u8 acpi_gbl_reg_methods_executed; +ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); /* Misc */ -ACPI_EXTERN u32 acpi_gbl_original_mode; -ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; -ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; -ACPI_EXTERN u32 acpi_gbl_ps_find_count; -ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; -ACPI_EXTERN u8 acpi_gbl_debugger_configuration; -ACPI_EXTERN u8 acpi_gbl_step_to_next_call; -ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; -ACPI_EXTERN u8 acpi_gbl_events_initialized; -ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces; -ACPI_EXTERN struct acpi_address_range - *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX]; - -#ifndef DEFINE_ACPI_GLOBALS - -/* Other miscellaneous */ - -extern u8 acpi_gbl_shutdown; -extern u32 acpi_gbl_startup_flags; +ACPI_GLOBAL(u32, acpi_gbl_original_mode); +ACPI_GLOBAL(u32, acpi_gbl_rsdp_original_location); +ACPI_GLOBAL(u32, acpi_gbl_ns_lookup_count); +ACPI_GLOBAL(u32, acpi_gbl_ps_find_count); +ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save); +ACPI_GLOBAL(u8, acpi_gbl_debugger_configuration); +ACPI_GLOBAL(u8, acpi_gbl_step_to_next_call); +ACPI_GLOBAL(u8, acpi_gbl_acpi_hardware_present); +ACPI_GLOBAL(u8, acpi_gbl_events_initialized); +ACPI_GLOBAL(struct acpi_interface_info *, acpi_gbl_supported_interfaces); +ACPI_GLOBAL(struct acpi_address_range *, + acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX]); + +/* Other miscellaneous, declared and initialized in utglobal */ + extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS]; extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS]; -extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; - -#endif +extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; #ifdef ACPI_DBG_TRACK_ALLOCATIONS -/* Lists for tracking memory allocations */ +/* Lists for tracking memory allocations (debug only) */ -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; -ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; -ACPI_EXTERN u8 acpi_gbl_disable_mem_tracking; +ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_global_list); +ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_ns_node_list); +ACPI_GLOBAL(u8, acpi_gbl_display_final_mem_stats); +ACPI_GLOBAL(u8, acpi_gbl_disable_mem_tracking); #endif /***************************************************************************** @@ -350,22 +337,23 @@ ACPI_EXTERN u8 acpi_gbl_disable_mem_tracking; #define NUM_PREDEFINED_NAMES 9 #endif -ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; -ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list; +ACPI_GLOBAL(struct acpi_namespace_node, acpi_gbl_root_node_struct); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_root_node); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_fadt_gpe_device); +ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_module_code_list); extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES]; #ifdef ACPI_DEBUG_OUTPUT -ACPI_EXTERN u32 acpi_gbl_current_node_count; -ACPI_EXTERN u32 acpi_gbl_current_node_size; -ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; -ACPI_EXTERN acpi_size *acpi_gbl_entry_stack_pointer; -ACPI_EXTERN acpi_size *acpi_gbl_lowest_stack_pointer; -ACPI_EXTERN u32 acpi_gbl_deepest_nesting; +ACPI_GLOBAL(u32, acpi_gbl_current_node_count); +ACPI_GLOBAL(u32, acpi_gbl_current_node_size); +ACPI_GLOBAL(u32, acpi_gbl_max_concurrent_node_count); +ACPI_GLOBAL(acpi_size *, acpi_gbl_entry_stack_pointer); +ACPI_GLOBAL(acpi_size *, acpi_gbl_lowest_stack_pointer); +ACPI_GLOBAL(u32, acpi_gbl_deepest_nesting); +ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0); #endif /***************************************************************************** @@ -374,11 +362,11 @@ ACPI_EXTERN u32 acpi_gbl_deepest_nesting; * ****************************************************************************/ -ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list; +ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list); /* Control method single step flag */ -ACPI_EXTERN u8 acpi_gbl_cm_single_step; +ACPI_GLOBAL(u8, acpi_gbl_cm_single_step); /***************************************************************************** * @@ -388,8 +376,9 @@ ACPI_EXTERN u8 acpi_gbl_cm_single_step; extern struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; -ACPI_EXTERN u8 acpi_gbl_sleep_type_a; -ACPI_EXTERN u8 acpi_gbl_sleep_type_b; + +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); /***************************************************************************** * @@ -399,14 +388,15 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b; #if (!ACPI_REDUCED_HARDWARE) -ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; -ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; -ACPI_EXTERN struct acpi_gpe_block_info - *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; -ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler; -ACPI_EXTERN void *acpi_gbl_global_event_handler_context; -ACPI_EXTERN struct acpi_fixed_event_handler - acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; +ACPI_GLOBAL(u8, acpi_gbl_all_gpes_initialized); +ACPI_GLOBAL(struct acpi_gpe_xrupt_info *, acpi_gbl_gpe_xrupt_list_head); +ACPI_GLOBAL(struct acpi_gpe_block_info *, + acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]); +ACPI_GLOBAL(acpi_gbl_event_handler, acpi_gbl_global_event_handler); +ACPI_GLOBAL(void *, acpi_gbl_global_event_handler_context); +ACPI_GLOBAL(struct acpi_fixed_event_handler, + acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]); + extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; @@ -418,23 +408,19 @@ extern struct acpi_fixed_event_info * ****************************************************************************/ -/* Procedure nesting level for debug output */ - -extern u32 acpi_gbl_nesting_level; - /* Event counters */ -ACPI_EXTERN u32 acpi_method_count; -ACPI_EXTERN u32 acpi_gpe_count; -ACPI_EXTERN u32 acpi_sci_count; -ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; +ACPI_GLOBAL(u32, acpi_method_count); +ACPI_GLOBAL(u32, acpi_gpe_count); +ACPI_GLOBAL(u32, acpi_sci_count); +ACPI_GLOBAL(u32, acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]); /* Support for dynamic control method tracing mechanism */ -ACPI_EXTERN u32 acpi_gbl_original_dbg_level; -ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; +ACPI_GLOBAL(u32, acpi_gbl_original_dbg_level); +ACPI_GLOBAL(u32, acpi_gbl_original_dbg_layer); +ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_level); +ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); /***************************************************************************** * @@ -442,61 +428,64 @@ ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; * ****************************************************************************/ -ACPI_EXTERN u8 acpi_gbl_db_output_flags; +ACPI_GLOBAL(u8, acpi_gbl_db_output_flags); #ifdef ACPI_DISASSEMBLER -ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE); +/* Do not disassemble buffers to resource descriptors */ + +ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE); -ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; -ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; -ACPI_EXTERN u8 acpi_gbl_num_external_methods; -ACPI_EXTERN u32 acpi_gbl_resolved_external_methods; -ACPI_EXTERN struct acpi_external_list *acpi_gbl_external_list; -ACPI_EXTERN struct acpi_external_file *acpi_gbl_external_file_list; +ACPI_GLOBAL(u8, acpi_gbl_db_opt_disasm); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_verbose); +ACPI_GLOBAL(u8, acpi_gbl_num_external_methods); +ACPI_GLOBAL(u32, acpi_gbl_resolved_external_methods); +ACPI_GLOBAL(struct acpi_external_list *, acpi_gbl_external_list); +ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list); #endif #ifdef ACPI_DEBUGGER -extern u8 acpi_gbl_method_executing; -extern u8 acpi_gbl_abort_method; -extern u8 acpi_gbl_db_terminate_threads; +ACPI_INIT_GLOBAL(u8, acpi_gbl_db_terminate_threads, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE); -ACPI_EXTERN u8 acpi_gbl_db_opt_tables; -ACPI_EXTERN u8 acpi_gbl_db_opt_stats; -ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; -ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support; -ACPI_EXTERN u8 acpi_gbl_db_output_to_file; -ACPI_EXTERN char *acpi_gbl_db_buffer; -ACPI_EXTERN char *acpi_gbl_db_filename; -ACPI_EXTERN u32 acpi_gbl_db_debug_level; -ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; +ACPI_GLOBAL(u8, acpi_gbl_db_opt_tables); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_stats); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_ini_methods); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_region_support); +ACPI_GLOBAL(u8, acpi_gbl_db_output_to_file); +ACPI_GLOBAL(char *, acpi_gbl_db_buffer); +ACPI_GLOBAL(char *, acpi_gbl_db_filename); +ACPI_GLOBAL(u32, acpi_gbl_db_debug_level); +ACPI_GLOBAL(u32, acpi_gbl_db_console_debug_level); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_db_scope_node); -ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_GLOBAL(char *, acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]); +ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]); /* These buffers should all be the same size */ -ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]); /* * Statistic globals */ -ACPI_EXTERN u16 acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]; -ACPI_EXTERN u16 acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]; -ACPI_EXTERN u16 acpi_gbl_obj_type_count_misc; -ACPI_EXTERN u16 acpi_gbl_node_type_count_misc; -ACPI_EXTERN u32 acpi_gbl_num_nodes; -ACPI_EXTERN u32 acpi_gbl_num_objects; - -ACPI_EXTERN u32 acpi_gbl_size_of_parse_tree; -ACPI_EXTERN u32 acpi_gbl_size_of_method_trees; -ACPI_EXTERN u32 acpi_gbl_size_of_node_entries; -ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects; +ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); +ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); +ACPI_GLOBAL(u16, acpi_gbl_obj_type_count_misc); +ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc); +ACPI_GLOBAL(u32, acpi_gbl_num_nodes); +ACPI_GLOBAL(u32, acpi_gbl_num_objects); + +ACPI_GLOBAL(u32, acpi_gbl_size_of_parse_tree); +ACPI_GLOBAL(u32, acpi_gbl_size_of_method_trees); +ACPI_GLOBAL(u32, acpi_gbl_size_of_node_entries); +ACPI_GLOBAL(u32, acpi_gbl_size_of_acpi_objects); #endif /* ACPI_DEBUGGER */ @@ -508,7 +497,7 @@ ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects; #ifdef ACPI_APPLICATION -ACPI_FILE ACPI_INIT_GLOBAL(acpi_gbl_debug_file, NULL); +ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); #endif /* ACPI_APPLICATION */ diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 6357e932bfd9..2ad2351a9833 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 8af8c9bdeb35..c54267748be5 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,6 +87,10 @@ typedef const struct acpi_exdump_info { #define ACPI_EXD_PACKAGE 11 #define ACPI_EXD_FIELD 12 #define ACPI_EXD_REFERENCE 13 +#define ACPI_EXD_LIST 14 /* Operand object list */ +#define ACPI_EXD_HDLR_LIST 15 /* Address Handler list */ +#define ACPI_EXD_RGN_LIST 16 /* Region list */ +#define ACPI_EXD_NODE 17 /* Namespace Node */ /* restore default alignment */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index d95ca5449ace..52a21dafb540 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 2a86c65d873b..4bceb11c7380 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,17 +63,21 @@ #define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) /* - * printf() format helpers + * printf() format helpers. These macros are workarounds for the difficulties + * with emitting 64-bit integers and 64-bit pointers with the same code + * for both 32-bit and 64-bit hosts. */ - -/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ - #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) #if ACPI_MACHINE_WIDTH == 64 #define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#define ACPI_FORMAT_TO_UINT(i) ACPI_FORMAT_UINT64(i) +#define ACPI_PRINTF_UINT "0x%8.8X%8.8X" + #else -#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (u32) (i) +#define ACPI_FORMAT_TO_UINT(i) (u32) (i) +#define ACPI_PRINTF_UINT "0x%8.8X" #endif /* diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index e6138ac4a160..ee1c040f321c 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index cc7ab6dd724e..1a4d61805ebc 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index 3fc9ca7e8aa3..dda0e6affcf1 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index aed319318835..6168b85463ed 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index f600aded7261..a48d713e9599 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ * * Return Package types * - * 1) PTYPE1 packages do not contain sub-packages. + * 1) PTYPE1 packages do not contain subpackages. * * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: * object type @@ -63,8 +63,8 @@ * (Used for _PRW) * * - * 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each - * of the different types describe the contents of each of the sub-packages. + * 2) PTYPE2 packages contain a Variable-length number of subpackages. Each + * of the different types describe the contents of each of the subpackages. * * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types. Zero-length * parent package is allowed: @@ -560,7 +560,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { /* * For _HPX, a single package is returned, containing a variable-length number - * of sub-packages. Each sub-package contains a PCI record setting. + * of subpackages. Each subpackage contains a PCI record setting. * There are several different type of record settings, of different * lengths, but all elements of all settings are Integers. */ @@ -698,6 +698,12 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + {{"_PRP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Str, 1 Int/Str/Pkg */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | + ACPI_RTYPE_PACKAGE | ACPI_RTYPE_REFERENCE, 1, 0), + {{"_PRS", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index ff97430455cb..4b008e8884a1 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index fc83c0a5ca70..5d2989a1b68c 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index c54f42c64fe2..5fa4b2027697 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index be8180c17d7e..ceeec0b7ccb1 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[]; /* Strings used by the disassembler and debugger resource dump routines */ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) extern const char *acpi_gbl_bm_decode[]; extern const char *acpi_gbl_config_decode[]; diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 48a3e331b72d..5908ccec6aea 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 87c26366d1df..f3f834408441 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index afdc6df17abf..720b1cdda711 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index eb56b66444b5..8daf9de82b73 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index e7a57c554e84..3661c8e90540 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 14424200d246..96644d5ac0e1 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 81a78ba84311..2c6d42c2bc01 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index c4b0b3657237..b67522df01ac 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index b1746a68dad1..a1e7e6b6fcf7 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 5205edcf2c01..6c0759c0db47 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index d7f53fb2979a..9f74795e2268 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 1bbb22fd6fa0..f7f5107e754d 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 2dbe109727c8..bd7811c64169 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index 7f569d573027..2ac28d297305 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index d67891de1b54..9d6e2c1de1f8 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index ecb12e2137ff..24f7d5ea678a 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 83cd45f4a870..c7bffff9ed32 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index 4c67193a9fa7..3393a73ca0d6 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index a9cb4a1a4bb8..955f83da68a5 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index a31e549e64cc..caaed3c673fd 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index a3e2f38aadf6..ae779c1e871d 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index 4d764e847a08..17e4bbfdb096 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index e3157313eb27..78ac29351c9e 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index a5687540e9a6..5d594eb2e5ec 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 144cbb9b73bc..9957297d1580 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -314,6 +314,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, { union acpi_operand_object *handler_obj; union acpi_operand_object *obj_desc; + union acpi_operand_object *start_desc; union acpi_operand_object **last_obj_ptr; acpi_adr_space_setup region_setup; void **region_context; @@ -341,6 +342,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, /* Find this region in the handler's list */ obj_desc = handler_obj->address_space.region_list; + start_desc = obj_desc; last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { @@ -438,6 +440,15 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, last_obj_ptr = &obj_desc->region.next; obj_desc = obj_desc->region.next; + + /* Prevent infinite loop if list is corrupted */ + + if (obj_desc == start_desc) { + ACPI_ERROR((AE_INFO, + "Circular handler list in region object %p", + region_obj)); + return_VOID; + } } /* If we get here, the region was not in the handler's region list */ diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 8354c4f7f10c..1b148a440d67 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 9e9e3454d893..4d8a709c1fc4 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 23a7fadca412..a734b27da061 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 39d06af5e347..e286640ad4ff 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 5713da77c665..20a1392ffe06 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -583,6 +583,18 @@ acpi_install_gpe_block(acpi_handle gpe_device, goto unlock_and_exit; } + /* Validate the parent device */ + + if (node->type != ACPI_TYPE_DEVICE) { + status = AE_TYPE; + goto unlock_and_exit; + } + + if (node->object) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + /* * For user-installed GPE Block Devices, the gpe_block_base_number * is always zero @@ -666,6 +678,13 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) goto unlock_and_exit; } + /* Validate the parent device */ + + if (node->type != ACPI_TYPE_DEVICE) { + status = AE_TYPE; + goto unlock_and_exit; + } + /* Get the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 02ed75ac56cd..2d6f187939c7 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 06d216c8d43a..8ba1464efd11 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 69e4a8cc9b71..c545386fee96 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 3c2e6dcdad3e..95d23dabcfbb 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index 81c72a4ecd82..4cfc3d3b5c97 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 4d046faac48c..973fdae00f94 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, {ACPI_EXD_BUFFER, 0, NULL} }; -static struct acpi_exdump_info acpi_ex_dump_package[5] = { +static struct acpi_exdump_info acpi_ex_dump_package[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(package.node), "Parent Node"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"}, @@ -108,11 +109,11 @@ static struct acpi_exdump_info acpi_ex_dump_package[5] = { static struct acpi_exdump_info acpi_ex_dump_device[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[0]), "System Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[1]), - "Device Notify"} + "Device Notify"}, + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(device.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_event[2] = { @@ -142,17 +143,18 @@ static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} }; -static struct acpi_exdump_info acpi_ex_dump_region[7] = { +static struct acpi_exdump_info acpi_ex_dump_region[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(region.node), "Parent Node"}, {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"}, + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(region.handler), "Handler"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"} }; -static struct acpi_exdump_info acpi_ex_dump_power[5] = { +static struct acpi_exdump_info acpi_ex_dump_power[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level), "System Level"}, @@ -161,7 +163,8 @@ static struct acpi_exdump_info acpi_ex_dump_power[5] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[0]), "System Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[1]), - "Device Notify"} + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_processor[7] = { @@ -225,7 +228,7 @@ static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(reference.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, {ACPI_EXD_REFERENCE, 0, NULL} }; @@ -234,16 +237,16 @@ static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list), + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(address_space.next), "Next"}, + {ACPI_EXD_RGN_LIST, ACPI_EXD_OFFSET(address_space.region_list), "Region List"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(address_space.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} }; static struct acpi_exdump_info acpi_ex_dump_notify[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(notify.node), "Node"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(notify.handler_type), "Handler Type"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.handler), "Handler"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}, @@ -252,14 +255,31 @@ static struct acpi_exdump_info acpi_ex_dump_notify[7] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[1]), "Next Device Notify"} }; +static struct acpi_exdump_info acpi_ex_dump_extra[6] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_extra), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.method_REG), "_REG Method"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(extra.scope_node), "Scope Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.region_context), + "Region Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.aml_start), "Aml Start"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(extra.aml_length), "Aml Length"} +}; + +static struct acpi_exdump_info acpi_ex_dump_data[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_data), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(data.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(data.pointer), "Raw Data"} +}; + /* Miscellaneous tables */ -static struct acpi_exdump_info acpi_ex_dump_common[4] = { +static struct acpi_exdump_info acpi_ex_dump_common[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL}, {ACPI_EXD_TYPE, 0, NULL}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count), "Reference Count"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"} + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"}, + {ACPI_EXD_LIST, ACPI_EXD_OFFSET(common.next_object), "Object List"} }; static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { @@ -274,15 +294,17 @@ static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { "Field Bit Offset"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset), "Base Byte Offset"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} }; -static struct acpi_exdump_info acpi_ex_dump_node[5] = { +static struct acpi_exdump_info acpi_ex_dump_node[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} + {ACPI_EXD_LIST, ACPI_EXD_NSOFFSET(object), "Object List"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(parent), "Parent"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(child), "Child"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(peer), "Peer"} }; /* Dispatch table, indexed by object type */ @@ -315,7 +337,9 @@ static struct acpi_exdump_info *acpi_ex_dump_info[] = { acpi_ex_dump_address_handler, NULL, NULL, - NULL + NULL, + acpi_ex_dump_extra, + acpi_ex_dump_data }; /******************************************************************************* @@ -340,6 +364,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, char *name; const char *reference_name; u8 count; + union acpi_operand_object *start; + union acpi_operand_object *data = NULL; + union acpi_operand_object *next; + struct acpi_namespace_node *node; if (!info) { acpi_os_printf @@ -363,9 +391,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_TYPE: - acpi_ex_out_string("Type", - acpi_ut_get_object_type_name - (obj_desc)); + acpi_os_printf("%20s : %2.2X [%s]\n", "Type", + obj_desc->common.type, + acpi_ut_get_object_type_name(obj_desc)); break; case ACPI_EXD_UINT8: @@ -433,6 +461,121 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, acpi_ex_dump_reference_obj(obj_desc); break; + case ACPI_EXD_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->common.next_object) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->common.next_object; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Object list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_HDLR_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->address_space.next) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->address_space.next; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Handler list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_RGN_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->region.next) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->region.next; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Region list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_NODE: + + node = + *ACPI_CAST_PTR(struct acpi_namespace_node *, + target); + + acpi_os_printf("%20s : %p", name, node); + if (node) { + acpi_os_printf(" [%4.4s]", node->name.ascii); + } + acpi_os_printf("\n"); + break; + default: acpi_os_printf("**** Invalid table opcode [%X] ****\n", @@ -821,10 +964,8 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) } acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); - acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); - acpi_ex_out_pointer("Attached Object", - acpi_ns_get_attached_object(node)); - acpi_ex_out_pointer("Parent", node->parent); + acpi_os_printf("%20s : %2.2X [%s]\n", "Type", + node->type, acpi_ut_get_type_name(node->type)); acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), acpi_ex_dump_node); @@ -1017,22 +1158,26 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) ((struct acpi_namespace_node *)obj_desc)-> object); - acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *) - obj_desc)->object, flags); - return_VOID; + obj_desc = ((struct acpi_namespace_node *)obj_desc)->object; + goto dump_object; } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf - ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", - obj_desc, acpi_ut_get_descriptor_name(obj_desc)); + acpi_os_printf("%p is not an ACPI operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name(obj_desc)); return_VOID; } - if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { + /* Validate the object type */ + + if (obj_desc->common.type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf("Not a known object type: %2.2X\n", + obj_desc->common.type); return_VOID; } +dump_object: + /* Common Fields */ acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); @@ -1040,6 +1185,22 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) /* Object-specific fields */ acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]); + + if (obj_desc->common.type == ACPI_TYPE_REGION) { + obj_desc = obj_desc->common.next_object; + if (obj_desc->common.type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf + ("Secondary object is not a known object type: %2.2X\n", + obj_desc->common.type); + + return_VOID; + } + + acpi_os_printf("\nExtra attached Object (%p):\n", obj_desc); + acpi_ex_dump_object(obj_desc, + acpi_ex_dump_info[obj_desc->common.type]); + } + return_VOID; } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index cfd875243421..68d97441432c 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 49fb742d61b9..1d1b27a96c5b 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 65d93607f368..2207e624f538 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 7be0205ad067..b49ea2a95f4f 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index 14689dec4960..dbb03b544e8c 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index d74cea416ca0..1b8e94104407 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index d6fa0fce1fc9..2ede656ee26a 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index bc042adf8804..363767cf01e5 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 4459e32c683d..29e9e99f7fe3 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 5a588611ab48..ee3f872870bc 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 9d28867e60dc..cd5288a257a9 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 7ca6925a87ca..ab060261b43e 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index 1606524312e3..3cde553bcbe1 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index be3f66973ee8..3af8de3fcea4 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index f0b09bf9887d..daf49f7ea311 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 20d809d90c5b..04bd16c08f9e 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index 26e371073b1a..fd11018b0168 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 6578dee2e51b..841caed11c08 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 99dc7b287d55..5b16c5484bee 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 3d36df828f52..1e66d960fc11 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 414076818d40..858fdd6be598 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 96540506058f..2e6caabba07a 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index 0889a629505f..e701d8c33dbf 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 12e6cff54f78..e0fd9b4978cd 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index e3828cc4361b..d590693eb54e 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index 3c498dc1636e..76ab5c1a814e 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index eab70d58852a..6b919127cd9d 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index b4b47db2dee2..96d007df65ec 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 15dddc10fc9b..6921c7f3d208 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 14f65f6345b9..f1249e3463be 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index fd1ff54cda19..607eb9e5150d 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c index 74b24c82707e..80fcfc8c9c1b 100644 --- a/drivers/acpi/acpica/nsarguments.c +++ b/drivers/acpi/acpica/nsarguments.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index acd2964c2690..b55642c4ee58 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 48b9c6f12643..3d88ef4a3e0d 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 283762511b73..42d37109aa5d 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 963ceef063f8..e634a05974db 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 3a0423af968c..5b74677bf74d 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 89ec645e7730..7ae521ce8d3f 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 90a0380fb8a0..7eee0a6f02f6 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index 7a736f4d1fd8..fe54a8c73b8c 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -222,13 +222,19 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) } } - /* Clear the entry in all cases */ + /* Clear the Node entry in all cases */ node->object = NULL; if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { + + /* Unlink object from front of possible object list */ + node->object = obj_desc->common.next_object; + + /* Handle possible 2-descriptor object */ + if (node->object && - ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) { + (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } } diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 177857340271..e83cff31754b 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index d2855d9857c4..392910ffbed9 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 3d5391f9bcb5..68f725839eb6 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,12 +132,12 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, * Decode the type of the expected package contents * * PTYPE1 packages contain no subpackages - * PTYPE2 packages contain sub-packages + * PTYPE2 packages contain subpackages */ switch (package->ret_info.type) { case ACPI_PTYPE1_FIXED: /* - * The package count is fixed and there are no sub-packages + * The package count is fixed and there are no subpackages * * If package is too small, exit. * If package is larger than expected, issue warning but continue @@ -169,7 +169,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, case ACPI_PTYPE1_VAR: /* - * The package count is variable, there are no sub-packages, and all + * The package count is variable, there are no subpackages, and all * elements must be of the same type */ for (i = 0; i < count; i++) { @@ -185,7 +185,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, case ACPI_PTYPE1_OPTION: /* - * The package count is variable, there are no sub-packages. There are + * The package count is variable, there are no subpackages. There are * a fixed number of required elements, and a variable number of * optional elements. * @@ -242,7 +242,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, elements++; count--; - /* Examine the sub-packages */ + /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); @@ -250,7 +250,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, case ACPI_PTYPE2_PKG_COUNT: - /* First element is the (Integer) count of sub-packages to follow */ + /* First element is the (Integer) count of subpackages to follow */ status = acpi_ns_check_object_type(info, elements, ACPI_RTYPE_INTEGER, 0); @@ -270,7 +270,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, count = expected_count; elements++; - /* Examine the sub-packages */ + /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); @@ -283,9 +283,9 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, case ACPI_PTYPE2_FIX_VAR: /* * These types all return a single Package that consists of a - * variable number of sub-Packages. + * variable number of subpackages. * - * First, ensure that the first element is a sub-Package. If not, + * First, ensure that the first element is a subpackage. If not, * the BIOS may have incorrectly returned the object as a single * package instead of a Package of Packages (a common error if * there is only one entry). We may be able to repair this by @@ -310,7 +310,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, count = 1; } - /* Examine the sub-packages */ + /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); @@ -370,9 +370,9 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, u32 j; /* - * Validate each sub-Package in the parent Package + * Validate each subpackage in the parent Package * - * NOTE: assumes list of sub-packages contains no NULL elements. + * NOTE: assumes list of subpackages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to acpi_ns_remove_null_elements. */ @@ -389,7 +389,7 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, return (status); } - /* Examine the different types of expected sub-packages */ + /* Examine the different types of expected subpackages */ info->parent_package = sub_package; switch (package->ret_info.type) { @@ -450,14 +450,14 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, case ACPI_PTYPE2_FIXED: - /* Each sub-package has a fixed length */ + /* Each subpackage has a fixed length */ expected_count = package->ret_info2.count; if (sub_package->package.count < expected_count) { goto package_too_small; } - /* Check the type of each sub-package element */ + /* Check the type of each subpackage element */ for (j = 0; j < expected_count; j++) { status = @@ -475,14 +475,14 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, case ACPI_PTYPE2_MIN: - /* Each sub-package has a variable but minimum length */ + /* Each subpackage has a variable but minimum length */ expected_count = package->ret_info.count1; if (sub_package->package.count < expected_count) { goto package_too_small; } - /* Check the type of each sub-package element */ + /* Check the type of each subpackage element */ status = acpi_ns_check_package_elements(info, sub_elements, @@ -531,7 +531,7 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, (*sub_elements)->integer.value = expected_count; } - /* Check the type of each sub-package element */ + /* Check the type of each subpackage element */ status = acpi_ns_check_package_elements(info, @@ -557,10 +557,10 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, package_too_small: - /* The sub-package count was smaller than required */ + /* The subpackage count was smaller than required */ ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, - "Return Sub-Package[%u] is too small - found %u elements, expected %u", + "Return SubPackage[%u] is too small - found %u elements, expected %u", i, sub_package->package.count, expected_count)); return (AE_AML_OPERAND_VALUE); diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index a05afff50eb9..7e417aa5c91e 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -207,13 +207,30 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info, * this predefined name. Either one return value is expected, or none, * for both methods and other objects. * - * Exit now if there is no return object. Warning if one was expected. + * Try to fix if there was no return object. Warning if failed to fix. */ if (!return_object) { if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { - ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, - ACPI_WARN_ALWAYS, - "Missing expected return value")); + if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, + ACPI_WARN_ALWAYS, + "Found unexpected NULL package element")); + + status = + acpi_ns_repair_null_element(info, + expected_btypes, + package_index, + return_object_ptr); + if (ACPI_SUCCESS(status)) { + return (AE_OK); /* Repair was successful */ + } + } else { + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, + ACPI_WARN_ALWAYS, + "Missing expected return value")); + } return (AE_AML_NO_RETURN_VALUE); } @@ -448,7 +465,7 @@ acpi_ns_repair_null_element(struct acpi_evaluate_info * info, * RETURN: None. * * DESCRIPTION: Remove all NULL package elements from packages that contain - * a variable number of sub-packages. For these types of + * a variable number of subpackages. For these types of * packages, NULL elements can be safely removed. * *****************************************************************************/ @@ -469,7 +486,7 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, /* * We can safely remove all NULL elements from these package types: * PTYPE1_VAR packages contain a variable number of simple data types. - * PTYPE2 packages contain a variable number of sub-packages. + * PTYPE2 packages contain a variable number of subpackages. */ switch (package_type) { case ACPI_PTYPE1_VAR: diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 6a25d320b169..b09e6bef72b8 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -432,8 +432,8 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info, * DESCRIPTION: Repair for the _CST object: * 1. Sort the list ascending by C state type * 2. Ensure type cannot be zero - * 3. A sub-package count of zero means _CST is meaningless - * 4. Count must match the number of C state sub-packages + * 3. A subpackage count of zero means _CST is meaningless + * 4. Count must match the number of C state subpackages * *****************************************************************************/ @@ -611,6 +611,7 @@ acpi_ns_repair_PRT(struct acpi_evaluate_info *info, union acpi_operand_object **top_object_list; union acpi_operand_object **sub_object_list; union acpi_operand_object *obj_desc; + union acpi_operand_object *sub_package; u32 element_count; u32 index; @@ -619,8 +620,17 @@ acpi_ns_repair_PRT(struct acpi_evaluate_info *info, top_object_list = package_object->package.elements; element_count = package_object->package.count; - for (index = 0; index < element_count; index++) { - sub_object_list = (*top_object_list)->package.elements; + /* Examine each subpackage */ + + for (index = 0; index < element_count; index++, top_object_list++) { + sub_package = *top_object_list; + sub_object_list = sub_package->package.elements; + + /* Check for minimum required element count */ + + if (sub_package->package.count < 4) { + continue; + } /* * If the BIOS has erroneously reversed the _PRT source_name (index 2) @@ -634,15 +644,12 @@ acpi_ns_repair_PRT(struct acpi_evaluate_info *info, sub_object_list[2] = obj_desc; info->return_flags |= ACPI_OBJECT_REPAIRED; - ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, info->node_flags, "PRT[%X]: Fixed reversed SourceName and SourceIndex", index)); } - - /* Point to the next union acpi_operand_object in the top level package */ - - top_object_list++; } return (AE_OK); @@ -679,7 +686,7 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info, u32 i; /* - * Entries (sub-packages) in the _PSS Package must be sorted by power + * Entries (subpackages) in the _PSS Package must be sorted by power * dissipation, in descending order. If it appears that the list is * incorrectly sorted, sort it. We sort by cpu_frequency, since this * should be proportional to the power. @@ -767,9 +774,9 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info, * * PARAMETERS: info - Method execution information block * return_object - Pointer to the top-level returned object - * start_index - Index of the first sub-package - * expected_count - Minimum length of each sub-package - * sort_index - Sub-package entry to sort on + * start_index - Index of the first subpackage + * expected_count - Minimum length of each subpackage + * sort_index - Subpackage entry to sort on * sort_direction - Ascending or descending * sort_key_name - Name of the sort_index field * @@ -805,7 +812,7 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, } /* - * NOTE: assumes list of sub-packages contains no NULL elements. + * NOTE: assumes list of subpackages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to acpi_ns_remove_null_elements. */ @@ -832,7 +839,7 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, return (AE_AML_OPERAND_TYPE); } - /* Each sub-package must have the minimum length */ + /* Each subpackage must have the minimum length */ if ((*outer_elements)->package.count < expected_count) { return (AE_AML_PACKAGE_LIMIT); diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 47420faef073..af1cc42a8aa1 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 4a0665b6bcc1..4a5e3f5c0ff7 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index e81f15ef659a..4758a1f2ce22 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 1f0c28ba50df..4bd558bf10d2 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data) /******************************************************************************* * - * FUNCTION: acpi_get_data + * FUNCTION: acpi_get_data_full * * PARAMETERS: obj_handle - Namespace node * handler - Handler used in call to attach_data * data - Where the data is returned + * callback - function to execute before returning * * RETURN: Status * - * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * DESCRIPTION: Retrieve data that was previously attached to a namespace node + * and execute a callback before returning. * ******************************************************************************/ acpi_status -acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler, + void **data, void (*callback)(void *)) { struct acpi_namespace_node *node; acpi_status status; @@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) } status = acpi_ns_get_attached_data(node, handler, data); + if (ACPI_SUCCESS(status) && callback) { + callback(*data); + } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } +ACPI_EXPORT_SYMBOL(acpi_get_data_full) + +/******************************************************************************* + * + * FUNCTION: acpi_get_data + * + * PARAMETERS: obj_handle - Namespace node + * handler - Handler used in call to attach_data + * data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +{ + return acpi_get_data_full(obj_handle, handler, data, NULL); +} + ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 3a4bd3ff49a3..8c6c11ce9760 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 0e6d79e462d4..dae9401be7a2 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 91a5a69db80c..314d314340ae 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 065b44ae538f..646d1a3f6e27 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index 95dc608a66a8..af1f46cd37a5 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index 1b659e59710a..1755d2ac5656 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c index b0c9787dbe61..0d8d37ffd04d 100644 --- a/drivers/acpi/acpica/psopinfo.c +++ b/drivers/acpi/acpica/psopinfo.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 79d9a28dedef..6d27b597394e 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 6a4b6fb39f32..32d250feea21 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index 877dc0de8df3..0b64181e7720 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 91fa73a6e55e..3cd48802eede 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index abd65624754f..9cb07e1e76d9 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index fcb7a840e996..e135acaa5e1c 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index f3a9276ac665..916fd095ff34 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index b60c9cf82862..689556744b03 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -636,7 +636,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, for (index = 0; index < number_of_elements; index++) { - /* Dereference the sub-package */ + /* Dereference the subpackage */ package_element = *top_object_list; diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 3a2ace93e62c..75d369050657 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -273,7 +273,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, */ user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); - /* Each sub-package must be of length 4 */ + /* Each subpackage must be of length 4 */ if ((*top_object_list)->package.count != 4) { ACPI_ERROR((AE_INFO, @@ -283,7 +283,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, } /* - * Dereference the sub-package. + * Dereference the subpackage. * The sub_object_list will now point to an array of the four IRQ * elements: [Address, Pin, Source, source_index] */ @@ -292,7 +292,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 1) First subobject: Dereference the PRT.Address */ obj_desc = sub_object_list[0]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].Address) Need Integer, found %s", index, @@ -305,7 +305,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 2) Second subobject: Dereference the PRT.Pin */ obj_desc = sub_object_list[1]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s", index, @@ -394,7 +394,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ obj_desc = sub_object_list[3]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].SourceIndex) Need Integer, found %s", index, diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 8a2d4986b0aa..c3c56b5a9788 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,8 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsdump") -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) /* Local prototypes */ static void acpi_rs_out_string(char *title, char *value); diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c index 46192bd53653..2f9332d5c973 100644 --- a/drivers/acpi/acpica/rsdumpinfo.c +++ b/drivers/acpi/acpica/rsdumpinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsdumpinfo") -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) #define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) #define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) #define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index 41fed78e0de6..9d3f8a9a24bd 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,8 +132,7 @@ struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = { acpi_rs_convert_uart_serial_bus, }; -#ifdef ACPI_FUTURE_USAGE -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) /* Dispatch table for resource dump functions */ @@ -168,7 +167,6 @@ struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = { }; #endif -#endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. * Includes size of the descriptor header (1 byte for small descriptors, diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index ca183755a6f9..19d64873290a 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index 364decc1028a..3461f7db26df 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 6053aa182093..77291293af64 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index ebc773a1b350..eab4483ff5f8 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index c99cec9cefde..41eea4bc089c 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c index fe49fc43e10f..9e8407223d95 100644 --- a/drivers/acpi/acpica/rsserial.c +++ b/drivers/acpi/acpica/rsserial.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 14a7982c9961..897a5ceb0420 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 01e476988aae..877ab9202133 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 8f89263ac47e..ec14588254d4 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index e4f4f02d49e7..c12003947bd5 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 634357d51fe9..e3040947e9a0 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -292,10 +292,11 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header new_table = acpi_os_map_memory(new_address, new_table_length); if (!new_table) { ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, - "%4.4s %p Attempted physical table override failed", + "%4.4s " ACPI_PRINTF_UINT + " Attempted physical table override failed", table_header->signature, - ACPI_CAST_PTR(void, - table_desc->address))); + ACPI_FORMAT_TO_UINT(table_desc-> + address))); return (NULL); } @@ -308,11 +309,11 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header finish_override: - ACPI_INFO((AE_INFO, - "%4.4s %p %s table override, new table: %p", + ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT + " %s table override, new table: " ACPI_PRINTF_UINT, table_header->signature, - ACPI_CAST_PTR(void, table_desc->address), - override_type, new_table)); + ACPI_FORMAT_TO_UINT(table_desc->address), + override_type, ACPI_FORMAT_TO_UINT(new_table))); /* We can now unmap/delete the original table (if fully mapped) */ diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 6866e767ba90..df3bb20ea325 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -128,15 +128,17 @@ acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header local_header; /* - * The reason that the Address is cast to a void pointer is so that we - * can use %p which will work properly on both 32-bit and 64-bit hosts. + * The reason that we use ACPI_PRINTF_UINT and ACPI_FORMAT_TO_UINT is to + * support both 32-bit and 64-bit hosts/addresses in a consistent manner. + * The %p specifier does not emit uniform output on all hosts. On some, + * leading zeros are not supported. */ if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { /* FACS only has signature and length fields */ - ACPI_INFO((AE_INFO, "%4.4s %p %06X", - header->signature, ACPI_CAST_PTR(void, address), + ACPI_INFO((AE_INFO, "%-4.4s " ACPI_PRINTF_UINT " %06X", + header->signature, ACPI_FORMAT_TO_UINT(address), header->length)); } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { @@ -147,8 +149,9 @@ acpi_tb_print_table_header(acpi_physical_address address, header)->oem_id, ACPI_OEM_ID_SIZE); acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)", - ACPI_CAST_PTR(void, address), + ACPI_INFO((AE_INFO, + "RSDP " ACPI_PRINTF_UINT " %06X (v%.2d %-6.6s)", + ACPI_FORMAT_TO_UINT(address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> revision > 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, @@ -162,8 +165,9 @@ acpi_tb_print_table_header(acpi_physical_address address, acpi_tb_cleanup_table_header(&local_header, header); ACPI_INFO((AE_INFO, - "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", - local_header.signature, ACPI_CAST_PTR(void, address), + "%-4.4s " ACPI_PRINTF_UINT + " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", + local_header.signature, ACPI_FORMAT_TO_UINT(address), local_header.length, local_header.revision, local_header.oem_id, local_header.oem_table_id, local_header.oem_revision, diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 6412d3c301cb..a4702eee91a8 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index db826eaadd1c..a1593159d9ea 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 60b5a871833c..0909420fc776 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index e4e1468877c3..65ab8fed3d5e 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 2c2b6ae5dfc4..a1acec9d2ef3 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index 1851762fc5b5..efac83c606dc 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c index 11fde93be120..3c1699740653 100644 --- a/drivers/acpi/acpica/utbuffer.c +++ b/drivers/acpi/acpica/utbuffer.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c index cacd2fd9e665..78fde0aac487 100644 --- a/drivers/acpi/acpica/utcache.c +++ b/drivers/acpi/acpica/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index edff4e653d9a..270c16464dd9 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -535,10 +535,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_LOCAL_REFERENCE: - /* TBD: should validate incoming handle */ + /* An incoming reference is defined to be a namespace node */ - internal_object->reference.class = ACPI_REFCLASS_NAME; - internal_object->reference.node = + internal_object->reference.class = ACPI_REFCLASS_REFOF; + internal_object->reference.object = external_object->reference.handle; break; diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index d971c8631263..21a20ac5b1e1 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index b3f31dd89a45..fbfa9eca011f 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index c07d2227ea42..a3516de213fa 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,6 +75,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) union acpi_operand_object *handler_desc; union acpi_operand_object *second_desc; union acpi_operand_object *next_desc; + union acpi_operand_object *start_desc; union acpi_operand_object **last_obj_ptr; ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); @@ -235,10 +236,11 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) if (handler_desc) { next_desc = handler_desc->address_space.region_list; + start_desc = next_desc; last_obj_ptr = &handler_desc->address_space.region_list; - /* Remove the region object from the handler's list */ + /* Remove the region object from the handler list */ while (next_desc) { if (next_desc == object) { @@ -247,10 +249,19 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) break; } - /* Walk the linked list of handler */ + /* Walk the linked list of handlers */ last_obj_ptr = &next_desc->region.next; next_desc = next_desc->region.next; + + /* Prevent infinite loop if list is corrupted */ + + if (next_desc == start_desc) { + ACPI_ERROR((AE_INFO, + "Circular region list in address handler object %p", + handler_desc)); + return_VOID; + } } if (handler_desc->address_space.handler_flags & diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c index 154fdcaa5830..8e544d4688cd 100644 --- a/drivers/acpi/acpica/uterror.c +++ b/drivers/acpi/acpica/uterror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 16fb90506db7..8fed1482d228 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index 3cf7b597edb9..0403dcaabaf2 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 030cb0dc673c..f3abeae9d2f8 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,31 +55,27 @@ ACPI_MODULE_NAME("utglobal") * Static global variable initialization. * ******************************************************************************/ -/* - * We want the debug switches statically initialized so they - * are already set when the debugger is entered. - */ -/* Debug switch - level and trace mask */ +/* Debug output control masks */ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; -/* Debug switch - layer (component) mask */ - u32 acpi_dbg_layer = 0; -u32 acpi_gbl_nesting_level = 0; -/* Debugger globals */ +/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ -u8 acpi_gbl_db_terminate_threads = FALSE; -u8 acpi_gbl_abort_method = FALSE; -u8 acpi_gbl_method_executing = FALSE; +struct acpi_table_fadt acpi_gbl_FADT; +u32 acpi_gbl_trace_flags; +acpi_name acpi_gbl_trace_method_name; +u8 acpi_gbl_system_awake_and_running; +u32 acpi_current_gpe_count; -/* System flags */ - -u32 acpi_gbl_startup_flags = 0; - -/* System starts uninitialized */ +/* + * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning + * that the ACPI hardware is no longer required. A flag in the FADT indicates + * a reduced HW machine, and that flag is duplicated here for convenience. + */ +u8 acpi_gbl_reduced_hardware; -u8 acpi_gbl_shutdown = TRUE; +/* Various state name strings */ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S0_", @@ -335,7 +331,6 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_DSDT = NULL; acpi_gbl_cm_single_step = FALSE; - acpi_gbl_db_terminate_threads = FALSE; acpi_gbl_shutdown = FALSE; acpi_gbl_ns_lookup_count = 0; acpi_gbl_ps_find_count = 0; @@ -382,6 +377,10 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_disable_mem_tracking = FALSE; #endif +#ifdef ACPI_DEBUGGER + acpi_gbl_db_terminate_threads = FALSE; +#endif + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index bfca7b4b6731..4b12880e5b11 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index c5d1ac44c07d..5f56fc49021e 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index 5c26ad420344..dc6e96547f18 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 909fe66e1934..d44dee6ee10a 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 02f9101b65e4..2e2bb14e1099 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 08c323245584..82717fff9ffc 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index 517af700399d..dfa9009bfc87 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 8856bd37bc76..685766fc6ca8 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,31 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utosi") +/****************************************************************************** + * + * ACPICA policy for new _OSI strings: + * + * It is the stated policy of ACPICA that new _OSI strings will be integrated + * into this module as soon as possible after they are defined. It is strongly + * recommended that all ACPICA hosts mirror this policy and integrate any + * changes to this module as soon as possible. There are several historical + * reasons behind this policy: + * + * 1) New BIOSs tend to test only the case where the host responds TRUE to + * the latest version of Windows, which would respond to the latest/newest + * _OSI string. Not responding TRUE to the latest version of Windows will + * risk executing untested code paths throughout the DSDT and SSDTs. + * + * 2) If a new _OSI string is recognized only after a significant delay, this + * has the potential to cause problems on existing working machines because + * of the possibility that a new and different path through the ASL code + * will be executed. + * + * 3) New _OSI strings are tending to come out about once per year. A delay + * in recognizing a new string for a significant amount of time risks the + * release of another string which only compounds the initial problem. + * + *****************************************************************************/ /* * Strings supported by the _OSI predefined control method (which is * implemented internally within this module.) @@ -74,6 +99,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ + {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ /* Feature Group Strings */ diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c index eb3aca761369..36bec57ebd23 100644 --- a/drivers/acpi/acpica/utownerid.c +++ b/drivers/acpi/acpica/utownerid.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c index 2b1ce4cd3207..db30caff130a 100644 --- a/drivers/acpi/acpica/utpredef.c +++ b/drivers/acpi/acpica/utpredef.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 2c2accb9e534..14cb6c0c8be2 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,8 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utresrc") -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. * Used by both the disassembler and the debugger resource dump routines diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index 03c4c2febd84..1cc97a752c15 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 45c0eb26b33d..77219336c7e0 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index c0027773cccb..7d0ee969d781 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -276,7 +276,8 @@ acpi_ut_free_and_track(void *allocation, } acpi_os_free(debug_block); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n", + allocation, debug_block)); return_VOID; } diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index be322c83643a..502a8492dc83 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index f7edb88f6054..edd861102f1b 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 246ef68681f4..13380d818462 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index 312299721ba1..2a0f9e04d3a4 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 3650b2183227..c4dac7150960 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -12,7 +12,7 @@ config ACPI_APEI config ACPI_APEI_GHES bool "APEI Generic Hardware Error Source" - depends on ACPI_APEI && X86 + depends on ACPI_APEI select ACPI_HED select IRQ_WORK select GENERIC_ALLOCATOR diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 797a6938d051..9a2c63b20050 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -39,15 +39,13 @@ #include <linux/acpi.h> #include <linux/power_supply.h> +#include "battery.h" + #define PREFIX "ACPI: " #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF -#define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_DEVICE_NAME "Battery" -#define ACPI_BATTERY_NOTIFY_STATUS 0x80 -#define ACPI_BATTERY_NOTIFY_INFO 0x81 -#define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 /* Battery power unit: 0 means mW, 1 means mA */ #define ACPI_BATTERY_POWER_UNIT_MA 1 @@ -736,6 +734,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event) acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, acpi_battery_present(battery)); + acpi_notifier_call_chain(device, event, acpi_battery_present(battery)); /* acpi_battery_update could remove power_supply object */ if (old && battery->bat.dev) power_supply_changed(&battery->bat); diff --git a/drivers/acpi/battery.h b/drivers/acpi/battery.h new file mode 100644 index 000000000000..6c084976987d --- /dev/null +++ b/drivers/acpi/battery.h @@ -0,0 +1,10 @@ +#ifndef __ACPI_BATTERY_H +#define __ACPI_BATTERY_H + +#define ACPI_BATTERY_CLASS "battery" + +#define ACPI_BATTERY_NOTIFY_STATUS 0x80 +#define ACPI_BATTERY_NOTIFY_INFO 0x81 +#define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 + +#endif diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fcb59c21c68d..e7e5844c87d0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -311,9 +311,7 @@ static void acpi_bus_osc_support(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; #endif -#ifdef ACPI_HOTPLUG_OST capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; -#endif if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; @@ -340,60 +338,77 @@ static void acpi_bus_osc_support(void) */ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) { - struct acpi_device *device = NULL; + struct acpi_device *adev; struct acpi_driver *driver; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", - type, handle)); + acpi_status status; + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* TBD */ + acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); break; case ACPI_NOTIFY_DEVICE_CHECK: - /* TBD */ + acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); break; case ACPI_NOTIFY_DEVICE_WAKE: - /* TBD */ + acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n"); break; case ACPI_NOTIFY_EJECT_REQUEST: - /* TBD */ + acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); break; case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: + acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n"); /* TBD: Exactly what does 'light' mean? */ break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: - /* TBD */ + acpi_handle_err(handle, "Device cannot be configured due " + "to a frequency mismatch\n"); break; case ACPI_NOTIFY_BUS_MODE_MISMATCH: - /* TBD */ + acpi_handle_err(handle, "Device cannot be configured due " + "to a bus mode mismatch\n"); break; case ACPI_NOTIFY_POWER_FAULT: - /* TBD */ + acpi_handle_err(handle, "Device has suffered a power fault\n"); break; default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Received unknown/unsupported notification [%08x]\n", - type)); - break; + acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); + ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; + goto err; } - acpi_bus_get_device(handle, &device); - if (device) { - driver = device->driver; - if (driver && driver->ops.notify && - (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) - driver->ops.notify(device, type); + adev = acpi_bus_get_acpi_device(handle); + if (!adev) + goto err; + + driver = adev->driver; + if (driver && driver->ops.notify && + (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) + driver->ops.notify(adev, type); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + case ACPI_NOTIFY_DEVICE_CHECK: + case ACPI_NOTIFY_EJECT_REQUEST: + status = acpi_hotplug_schedule(adev, type); + if (ACPI_SUCCESS(status)) + return; + default: + break; } + acpi_bus_put_acpi_device(adev); + return; + + err: + acpi_evaluate_ost(handle, type, ost_code, NULL); } /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 714e957a871a..db35594d4df7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -302,6 +302,10 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) input_sync(input); pm_wakeup_event(&device->dev, 0); + acpi_bus_generate_netlink_event( + device->pnp.device_class, + dev_name(&device->dev), + event, ++button->pushed); } break; default: diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 368f9ddb8480..63119d09b354 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -31,8 +31,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); @@ -68,6 +66,9 @@ static int container_device_attach(struct acpi_device *adev, struct device *dev; int ret; + if (adev->flags.is_dock_station) + return 0; + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return -ENOMEM; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index c14a00d3dca6..d047739f3380 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -901,15 +901,30 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early); int acpi_subsys_prepare(struct device *dev) { /* - * Follow PCI and resume devices suspended at run time before running - * their system suspend callbacks. + * Devices having power.ignore_children set may still be necessary for + * suspending their children in the next phase of device suspend. */ - pm_runtime_resume(dev); + if (dev->power.ignore_children) + pm_runtime_resume(dev); + return pm_generic_prepare(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_prepare); /** + * acpi_subsys_suspend - Run the device driver's suspend callback. + * @dev: Device to handle. + * + * Follow PCI and resume devices suspended at run time before running their + * system suspend callbacks. + */ +int acpi_subsys_suspend(struct device *dev) +{ + pm_runtime_resume(dev); + return pm_generic_suspend(dev); +} + +/** * acpi_subsys_suspend_late - Suspend device using ACPI. * @dev: Device to suspend. * @@ -937,6 +952,23 @@ int acpi_subsys_resume_early(struct device *dev) return ret ? ret : pm_generic_resume_early(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_resume_early); + +/** + * acpi_subsys_freeze - Run the device driver's freeze callback. + * @dev: Device to handle. + */ +int acpi_subsys_freeze(struct device *dev) +{ + /* + * This used to be done in acpi_subsys_prepare() for all devices and + * some drivers may depend on it, so do it here. Ideally, however, + * runtime-suspended devices should not be touched during freeze/thaw + * transitions. + */ + pm_runtime_resume(dev); + return pm_generic_freeze(dev); +} + #endif /* CONFIG_PM_SLEEP */ static struct dev_pm_domain acpi_general_pm_domain = { @@ -947,8 +979,11 @@ static struct dev_pm_domain acpi_general_pm_domain = { #endif #ifdef CONFIG_PM_SLEEP .prepare = acpi_subsys_prepare, + .suspend = acpi_subsys_suspend, .suspend_late = acpi_subsys_suspend_late, .resume_early = acpi_subsys_resume_early, + .freeze = acpi_subsys_freeze, + .poweroff = acpi_subsys_suspend, .poweroff_late = acpi_subsys_suspend_late, .restore_early = acpi_subsys_resume_early, #endif diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 5bfd769fc91f..f0fc6260266b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -1,7 +1,9 @@ /* * dock.c - ACPI dock station driver * - * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com> + * Copyright (C) 2006, 2014, Intel Corp. + * Author: Kristen Carlson Accardi <kristen.c.accardi@intel.com> + * Rafael J. Wysocki <rafael.j.wysocki@intel.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -35,8 +37,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" ACPI_MODULE_NAME("dock"); @@ -68,15 +68,10 @@ struct dock_station { }; static LIST_HEAD(dock_stations); static int dock_station_count; -static DEFINE_MUTEX(hotplug_lock); struct dock_dependent_device { struct list_head list; - acpi_handle handle; - const struct acpi_dock_ops *hp_ops; - void *hp_context; - unsigned int hp_refcount; - void (*hp_release)(void *); + struct acpi_device *adev; }; #define DOCK_DOCKING 0x00000001 @@ -98,13 +93,13 @@ enum dock_callback_type { *****************************************************************************/ /** * add_dock_dependent_device - associate a device with the dock station - * @ds: The dock station - * @handle: handle of the dependent device + * @ds: Dock station. + * @adev: Dependent ACPI device object. * * Add the dependent device to the dock's dependent device list. */ -static int __init -add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) +static int add_dock_dependent_device(struct dock_station *ds, + struct acpi_device *adev) { struct dock_dependent_device *dd; @@ -112,180 +107,120 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) if (!dd) return -ENOMEM; - dd->handle = handle; + dd->adev = adev; INIT_LIST_HEAD(&dd->list); list_add_tail(&dd->list, &ds->dependent_devices); return 0; } -static void remove_dock_dependent_devices(struct dock_station *ds) +static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, + enum dock_callback_type cb_type) { - struct dock_dependent_device *dd, *aux; + struct acpi_device *adev = dd->adev; - list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) { - list_del(&dd->list); - kfree(dd); - } -} + acpi_lock_hp_context(); -/** - * dock_init_hotplug - Initialize a hotplug device on a docking station. - * @dd: Dock-dependent device. - * @ops: Dock operations to attach to the dependent device. - * @context: Data to pass to the @ops callbacks and @release. - * @init: Optional initialization routine to run after setting up context. - * @release: Optional release routine to run on removal. - */ -static int dock_init_hotplug(struct dock_dependent_device *dd, - const struct acpi_dock_ops *ops, void *context, - void (*init)(void *), void (*release)(void *)) -{ - int ret = 0; + if (!adev->hp) + goto out; - mutex_lock(&hotplug_lock); - if (WARN_ON(dd->hp_context)) { - ret = -EEXIST; - } else { - dd->hp_refcount = 1; - dd->hp_ops = ops; - dd->hp_context = context; - dd->hp_release = release; - if (init) - init(context); - } - mutex_unlock(&hotplug_lock); - return ret; -} + if (cb_type == DOCK_CALL_FIXUP) { + void (*fixup)(struct acpi_device *); -/** - * dock_release_hotplug - Decrement hotplug reference counter of dock device. - * @dd: Dock-dependent device. - * - * Decrement the reference counter of @dd and if 0, detach its hotplug - * operations from it, reset its context pointer and run the optional release - * routine if present. - */ -static void dock_release_hotplug(struct dock_dependent_device *dd) -{ - mutex_lock(&hotplug_lock); - if (dd->hp_context && !--dd->hp_refcount) { - void (*release)(void *) = dd->hp_release; - void *context = dd->hp_context; - - dd->hp_ops = NULL; - dd->hp_context = NULL; - dd->hp_release = NULL; - if (release) - release(context); - } - mutex_unlock(&hotplug_lock); -} + fixup = adev->hp->fixup; + if (fixup) { + acpi_unlock_hp_context(); + fixup(adev); + return; + } + } else if (cb_type == DOCK_CALL_UEVENT) { + void (*uevent)(struct acpi_device *, u32); + + uevent = adev->hp->uevent; + if (uevent) { + acpi_unlock_hp_context(); + uevent(adev, event); + return; + } + } else { + int (*notify)(struct acpi_device *, u32); -static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, - enum dock_callback_type cb_type) -{ - acpi_notify_handler cb = NULL; - bool run = false; - - mutex_lock(&hotplug_lock); - - if (dd->hp_context) { - run = true; - dd->hp_refcount++; - if (dd->hp_ops) { - switch (cb_type) { - case DOCK_CALL_FIXUP: - cb = dd->hp_ops->fixup; - break; - case DOCK_CALL_UEVENT: - cb = dd->hp_ops->uevent; - break; - default: - cb = dd->hp_ops->handler; - } + notify = adev->hp->notify; + if (notify) { + acpi_unlock_hp_context(); + notify(adev, event); + return; } } - mutex_unlock(&hotplug_lock); + out: + acpi_unlock_hp_context(); +} - if (!run) - return; +static struct dock_station *find_dock_station(acpi_handle handle) +{ + struct dock_station *ds; - if (cb) - cb(dd->handle, event, dd->hp_context); + list_for_each_entry(ds, &dock_stations, sibling) + if (ds->handle == handle) + return ds; - dock_release_hotplug(dd); + return NULL; } /** * find_dock_dependent_device - get a device dependent on this dock * @ds: the dock station - * @handle: the acpi_handle of the device we want + * @adev: ACPI device object to find. * * iterate over the dependent device list for this dock. If the * dependent device matches the handle, return. */ static struct dock_dependent_device * -find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) +find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev) { struct dock_dependent_device *dd; list_for_each_entry(dd, &ds->dependent_devices, list) - if (handle == dd->handle) + if (adev == dd->adev) return dd; return NULL; } -/***************************************************************************** - * Dock functions * - *****************************************************************************/ -static int __init is_battery(acpi_handle handle) +void register_dock_dependent_device(struct acpi_device *adev, + acpi_handle dshandle) { - struct acpi_device_info *info; - int ret = 1; + struct dock_station *ds = find_dock_station(dshandle); - if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) - return 0; - if (!(info->valid & ACPI_VALID_HID)) - ret = 0; - else - ret = !strcmp("PNP0C0A", info->hardware_id.string); - - kfree(info); - return ret; + if (ds && !find_dock_dependent_device(ds, adev)) + add_dock_dependent_device(ds, adev); } -/* Check whether ACPI object is an ejectable battery or disk bay */ -static bool __init is_ejectable_bay(acpi_handle handle) -{ - if (acpi_has_method(handle, "_EJ0") && is_battery(handle)) - return true; - - return acpi_bay_match(handle); -} +/***************************************************************************** + * Dock functions * + *****************************************************************************/ /** * is_dock_device - see if a device is on a dock station - * @handle: acpi handle of the device + * @adev: ACPI device object to check. * * If this device is either the dock station itself, * or is a device dependent on the dock station, then it * is a dock device */ -int is_dock_device(acpi_handle handle) +int is_dock_device(struct acpi_device *adev) { struct dock_station *dock_station; if (!dock_station_count) return 0; - if (acpi_dock_match(handle)) + if (acpi_dock_match(adev->handle)) return 1; list_for_each_entry(dock_station, &dock_stations, sibling) - if (find_dock_dependent_device(dock_station, handle)) + if (find_dock_dependent_device(dock_station, adev)) return 1; return 0; @@ -313,43 +248,6 @@ static int dock_present(struct dock_station *ds) } /** - * dock_create_acpi_device - add new devices to acpi - * @handle - handle of the device to add - * - * This function will create a new acpi_device for the given - * handle if one does not exist already. This should cause - * acpi to scan for drivers for the given devices, and call - * matching driver's add routine. - */ -static void dock_create_acpi_device(acpi_handle handle) -{ - struct acpi_device *device = NULL; - int ret; - - 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); - } -} - -/** - * dock_remove_acpi_device - remove the acpi_device struct from acpi - * @handle - the handle of the device to remove - * - * Tell acpi to remove the acpi_device. This should cause any loaded - * driver to have it's remove routine called. - */ -static void dock_remove_acpi_device(acpi_handle handle) -{ - struct acpi_device *device; - - if (!acpi_bus_get_device(handle, &device)) - acpi_bus_trim(device); -} - -/** * hot_remove_dock_devices - Remove dock station devices. * @ds: Dock station. */ @@ -366,7 +264,7 @@ static void hot_remove_dock_devices(struct dock_station *ds) dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false); list_for_each_entry_reverse(dd, &ds->dependent_devices, list) - dock_remove_acpi_device(dd->handle); + acpi_bus_trim(dd->adev); } /** @@ -392,12 +290,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) dock_hotplug_event(dd, event, DOCK_CALL_HANDLER); /* - * Now make sure that an acpi_device is created for each dependent - * device. That will cause scan handlers to be attached to device - * objects or acpi_drivers to be stopped/started if they are present. + * Check if all devices have been enumerated already. If not, run + * acpi_bus_scan() for them and that will cause scan handlers to be + * attached to device objects or acpi_drivers to be stopped/started if + * they are present. */ - list_for_each_entry(dd, &ds->dependent_devices, list) - dock_create_acpi_device(dd->handle); + list_for_each_entry(dd, &ds->dependent_devices, list) { + struct acpi_device *adev = dd->adev; + + if (!acpi_device_enumerated(adev)) { + int ret = acpi_bus_scan(adev->handle); + if (ret) + dev_dbg(&adev->dev, "scan error %d\n", -ret); + } + } } static void dock_event(struct dock_station *ds, u32 event, int num) @@ -501,71 +407,6 @@ static int dock_in_progress(struct dock_station *ds) } /** - * register_hotplug_dock_device - register a hotplug function - * @handle: the handle of the device - * @ops: handlers to call after docking - * @context: device specific data - * @init: Optional initialization routine to run after registration - * @release: Optional release routine to run on unregistration - * - * If a driver would like to perform a hotplug operation after a dock - * event, they can register an acpi_notifiy_handler to be called by - * the dock driver after _DCK is executed. - */ -int register_hotplug_dock_device(acpi_handle handle, - const struct acpi_dock_ops *ops, void *context, - void (*init)(void *), void (*release)(void *)) -{ - struct dock_dependent_device *dd; - struct dock_station *dock_station; - int ret = -EINVAL; - - if (WARN_ON(!context)) - return -EINVAL; - - if (!dock_station_count) - return -ENODEV; - - /* - * make sure this handle is for a device dependent on the dock, - * this would include the dock station itself - */ - list_for_each_entry(dock_station, &dock_stations, sibling) { - /* - * An ATA bay can be in a dock and itself can be ejected - * separately, so there are two 'dock stations' which need the - * ops - */ - dd = find_dock_dependent_device(dock_station, handle); - if (dd && !dock_init_hotplug(dd, ops, context, init, release)) - ret = 0; - } - - return ret; -} -EXPORT_SYMBOL_GPL(register_hotplug_dock_device); - -/** - * unregister_hotplug_dock_device - remove yourself from the hotplug list - * @handle: the acpi handle of the device - */ -void unregister_hotplug_dock_device(acpi_handle handle) -{ - struct dock_dependent_device *dd; - struct dock_station *dock_station; - - if (!dock_station_count) - return; - - list_for_each_entry(dock_station, &dock_stations, sibling) { - dd = find_dock_dependent_device(dock_station, handle); - if (dd) - dock_release_hotplug(dd); - } -} -EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); - -/** * handle_eject_request - handle an undock request checking for error conditions * * Check to make sure the dock device is still present, then undock and @@ -598,20 +439,23 @@ static int handle_eject_request(struct dock_station *ds, u32 event) } /** - * dock_notify - act upon an acpi dock notification - * @ds: dock station - * @event: the acpi event + * dock_notify - Handle ACPI dock notification. + * @adev: Dock station's ACPI device object. + * @event: Event code. * * If we are notified to dock, then check to see if the dock is * present and then dock. Notify all drivers of the dock event, * and then hotplug and devices that may need hotplugging. */ -static void dock_notify(struct dock_station *ds, u32 event) +int dock_notify(struct acpi_device *adev, u32 event) { - acpi_handle handle = ds->handle; - struct acpi_device *adev = NULL; + acpi_handle handle = adev->handle; + struct dock_station *ds = find_dock_station(handle); int surprise_removal = 0; + if (!ds) + return -ENODEV; + /* * According to acpi spec 3.0a, if a DEVICE_CHECK notification * is sent and _DCK is present, it is assumed to mean an undock @@ -632,7 +476,6 @@ static void dock_notify(struct dock_station *ds, u32 event) switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - acpi_bus_get_device(handle, &adev); if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) { begin_dock(ds); dock(ds); @@ -662,49 +505,8 @@ static void dock_notify(struct dock_station *ds, u32 event) else dock_event(ds, event, UNDOCK_EVENT); break; - default: - acpi_handle_err(handle, "Unknown dock event %d\n", event); } -} - -static void acpi_dock_deferred_cb(void *data, u32 event) -{ - acpi_scan_lock_acquire(); - dock_notify(data, event); - acpi_scan_lock_release(); -} - -static void dock_notify_handler(acpi_handle handle, u32 event, void *data) -{ - if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK - && event != ACPI_NOTIFY_EJECT_REQUEST) - return; - - acpi_hotplug_execute(acpi_dock_deferred_cb, data, event); -} - -/** - * find_dock_devices - find devices on the dock station - * @handle: the handle of the device we are examining - * @lvl: unused - * @context: the dock station private data - * @rv: unused - * - * This function is called by acpi_walk_namespace. It will - * check to see if an object has an _EJD method. If it does, then it - * will see if it is dependent on the dock station. - */ -static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - struct dock_station *ds = context; - acpi_handle ejd = NULL; - - acpi_bus_get_ejd(handle, &ejd); - if (ejd == ds->handle) - add_dock_dependent_device(ds, handle); - - return AE_OK; + return 0; } /* @@ -803,23 +605,28 @@ static struct attribute_group dock_attribute_group = { }; /** - * dock_add - add a new dock station - * @handle: the dock station handle + * acpi_dock_add - Add a new dock station + * @adev: Dock station ACPI device object. * - * allocated and initialize a new dock station device. Find all devices - * that are on the dock station, and register for dock event notifications. + * allocated and initialize a new dock station device. */ -static int __init dock_add(acpi_handle handle) +void acpi_dock_add(struct acpi_device *adev) { struct dock_station *dock_station, ds = { NULL, }; + struct platform_device_info pdevinfo; + acpi_handle handle = adev->handle; struct platform_device *dd; - acpi_status status; int ret; - dd = platform_device_register_data(NULL, "dock", dock_station_count, - &ds, sizeof(ds)); + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = "dock"; + pdevinfo.id = dock_station_count; + pdevinfo.acpi_node.companion = adev; + pdevinfo.data = &ds; + pdevinfo.size_data = sizeof(ds); + dd = platform_device_register_full(&pdevinfo); if (IS_ERR(dd)) - return PTR_ERR(dd); + return; dock_station = dd->dev.platform_data; @@ -837,72 +644,29 @@ static int __init dock_add(acpi_handle handle) dock_station->flags |= DOCK_IS_DOCK; if (acpi_ata_match(handle)) dock_station->flags |= DOCK_IS_ATA; - if (is_battery(handle)) + if (acpi_device_is_battery(adev)) dock_station->flags |= DOCK_IS_BAT; ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group); if (ret) goto err_unregister; - /* Find dependent devices */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_dock_devices, NULL, - dock_station, NULL); - /* add the dock station as a device dependent on itself */ - ret = add_dock_dependent_device(dock_station, handle); + ret = add_dock_dependent_device(dock_station, adev); if (ret) goto err_rmgroup; - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - dock_notify_handler, dock_station); - if (ACPI_FAILURE(status)) { - ret = -ENODEV; - goto err_rmgroup; - } - dock_station_count++; list_add(&dock_station->sibling, &dock_stations); - return 0; + adev->flags.is_dock_station = true; + dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n", + dock_station_count); + return; err_rmgroup: - remove_dock_dependent_devices(dock_station); sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group); + err_unregister: platform_device_unregister(dd); acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret); - return ret; -} - -/** - * find_dock_and_bay - look for dock stations and bays - * @handle: acpi handle of a device - * @lvl: unused - * @context: unused - * @rv: unused - * - * This is called by acpi_walk_namespace to look for dock stations and bays. - */ -static acpi_status __init -find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - if (acpi_dock_match(handle) || is_ejectable_bay(handle)) - dock_add(handle); - - return AE_OK; -} - -void __init acpi_dock_init(void) -{ - /* 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); - - if (!dock_station_count) { - pr_info(PREFIX "No dock devices found.\n"); - return; - } - - pr_info(PREFIX "%s: %d docks/bays found\n", - ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); } diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 09e423f3d8ad..8acf53e62966 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -55,11 +55,16 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev); static int acpi_fan_resume(struct device *dev); +static struct dev_pm_ops acpi_fan_pm = { + .resume = acpi_fan_resume, + .freeze = acpi_fan_suspend, + .thaw = acpi_fan_resume, + .restore = acpi_fan_resume, +}; +#define FAN_PM_OPS_PTR (&acpi_fan_pm) #else -#define acpi_fan_suspend NULL -#define acpi_fan_resume NULL +#define FAN_PM_OPS_PTR NULL #endif -static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume); static struct acpi_driver acpi_fan_driver = { .name = "fan", @@ -69,7 +74,7 @@ static struct acpi_driver acpi_fan_driver = { .add = acpi_fan_add, .remove = acpi_fan_remove, }, - .drv.pm = &acpi_fan_pm, + .drv.pm = FAN_PM_OPS_PTR, }; /* thermal cooling device callbacks */ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 0c789224d40d..f774c65ecb8b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -287,6 +287,7 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one); static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type = acpi_get_bus_type(dev); + struct acpi_device *adev; int ret; ret = acpi_bind_one(dev, NULL); @@ -303,9 +304,14 @@ static int acpi_platform_notify(struct device *dev) if (ret) goto out; } + adev = ACPI_COMPANION(dev); + if (!adev) + goto out; if (type && type->setup) type->setup(dev); + else if (adev->handler && adev->handler->bind) + adev->handler->bind(dev); out: #if ACPI_GLUE_DEBUG @@ -324,11 +330,17 @@ static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify_remove(struct device *dev) { + struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_bus_type *type; + if (!adev) + return 0; + type = acpi_get_bus_type(dev); if (type && type->cleanup) type->cleanup(dev); + else if (adev->handler && adev->handler->unbind) + adev->handler->unbind(dev); acpi_unbind_one(dev); return 0; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index dedbb2d802f1..957391306cbf 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -37,9 +37,15 @@ void acpi_container_init(void); static inline void acpi_container_init(void) {} #endif #ifdef CONFIG_ACPI_DOCK -void acpi_dock_init(void); +void register_dock_dependent_device(struct acpi_device *adev, + acpi_handle dshandle); +int dock_notify(struct acpi_device *adev, u32 event); +void acpi_dock_add(struct acpi_device *adev); #else -static inline void acpi_dock_init(void) {} +static inline void register_dock_dependent_device(struct acpi_device *adev, + acpi_handle dshandle) {} +static inline int dock_notify(struct acpi_device *adev, u32 event) { return -ENODEV; } +static inline void acpi_dock_add(struct acpi_device *adev) {} #endif #ifdef CONFIG_ACPI_HOTPLUG_MEMORY void acpi_memory_hotplug_init(void); @@ -72,7 +78,9 @@ void acpi_lpss_init(void); static inline void acpi_lpss_init(void) {} #endif +acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src); bool acpi_queue_hotplug_work(struct work_struct *work); +void acpi_device_hotplug(struct acpi_device *adev, u32 src); bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); /* -------------------------------------------------------------------------- @@ -90,6 +98,7 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, struct acpi_device *adev); int acpi_unbind_one(struct device *dev); bool acpi_device_is_present(struct acpi_device *adev); +bool acpi_device_is_battery(struct acpi_device *adev); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index fc1aa7909690..27f84af4e337 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -52,7 +52,7 @@ #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); -#define PREFIX "ACPI: " + struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; @@ -1168,8 +1168,7 @@ void acpi_os_wait_events_complete(void) struct acpi_hp_work { struct work_struct work; - acpi_hp_callback func; - void *data; + struct acpi_device *adev; u32 src; }; @@ -1178,25 +1177,24 @@ static void acpi_hotplug_work_fn(struct work_struct *work) struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work); acpi_os_wait_events_complete(); - hpw->func(hpw->data, hpw->src); + acpi_device_hotplug(hpw->adev, hpw->src); kfree(hpw); } -acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) +acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src) { struct acpi_hp_work *hpw; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Scheduling function [%p(%p, %u)] for deferred execution.\n", - func, data, src)); + "Scheduling hotplug event (%p, %u) for deferred execution.\n", + adev, src)); hpw = kmalloc(sizeof(*hpw), GFP_KERNEL); if (!hpw) return AE_NO_MEMORY; INIT_WORK(&hpw->work, acpi_hotplug_work_fn); - hpw->func = func; - hpw->data = data; + hpw->adev = adev; hpw->src = src; /* * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because @@ -1780,6 +1778,17 @@ static int __init acpi_no_auto_ssdt_setup(char *s) __setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); +static int __init acpi_disable_return_repair(char *s) +{ + printk(KERN_NOTICE PREFIX + "ACPI: Predefined validation mechanism disabled\n"); + acpi_gbl_disable_auto_repair = TRUE; + + return 1; +} + +__setup("acpica_no_return_repair", acpi_disable_return_repair); + acpi_status __init acpi_os_initialize(void) { acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block); diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 361b40c10c3f..9c62340c2360 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -370,6 +370,30 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) return NULL; } +#if IS_ENABLED(CONFIG_ISA) || IS_ENABLED(CONFIG_EISA) +static int acpi_isa_register_gsi(struct pci_dev *dev) +{ + u32 dev_gsi; + + /* Interrupt Line values above 0xF are forbidden */ + if (dev->irq > 0 && (dev->irq <= 0xF) && + (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { + dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n", + pin_name(dev->pin), dev->irq); + acpi_register_gsi(&dev->dev, dev_gsi, + ACPI_LEVEL_SENSITIVE, + ACPI_ACTIVE_LOW); + return 0; + } + return -EINVAL; +} +#else +static inline int acpi_isa_register_gsi(struct pci_dev *dev) +{ + return -ENODEV; +} +#endif + int acpi_pci_irq_enable(struct pci_dev *dev) { struct acpi_prt_entry *entry; @@ -416,19 +440,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * driver reported one, then use it. Exit in any case. */ if (gsi < 0) { - u32 dev_gsi; - /* Interrupt Line values above 0xF are forbidden */ - if (dev->irq > 0 && (dev->irq <= 0xF) && - (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { - dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n", - pin_name(pin), dev->irq); - acpi_register_gsi(&dev->dev, dev_gsi, - ACPI_LEVEL_SENSITIVE, - ACPI_ACTIVE_LOW); - } else { + if (acpi_isa_register_gsi(dev)) dev_warn(&dev->dev, "PCI INT %c: no GSI\n", pin_name(pin)); - } kfree(entry); return 0; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 9418c7a1f786..cfd7581cc19f 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -43,8 +43,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c1c4102e6478..d388f13d48b4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -39,8 +39,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" @@ -51,7 +49,7 @@ 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); + acpiphp_check_host_bridge(adev); return 0; } diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index ad7da686e6e6..e0bcfb642b52 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -46,8 +46,6 @@ #include "sleep.h" #include "internal.h" -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_POWER_COMPONENT ACPI_MODULE_NAME("power"); #define ACPI_POWER_CLASS "power_resource" diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a4eea9a508d3..86d73d5d503f 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -15,28 +15,9 @@ #include "internal.h" -#define PREFIX "ACPI: " #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_core"); -static int __init set_no_mwait(const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disabling mwait for CPU C-states\n", id->ident); - boot_option_idle_override = IDLE_NOMWAIT; - return 0; -} - -static struct dmi_system_id processor_idle_dmi_table[] __initdata = { - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; - static int map_lapic_id(struct acpi_subtable_header *entry, u32 acpi_id, int *apic_id) { @@ -89,6 +70,28 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, return 0; } +static int map_gic_id(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, int *apic_id) +{ + struct acpi_madt_generic_interrupt *gic = + (struct acpi_madt_generic_interrupt *)entry; + + if (!(gic->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* + * In the GIC interrupt model, logical processors are + * required to have a Processor Device object in the DSDT, + * so we should check device_declaration here + */ + if (device_declaration && (gic->uid == acpi_id)) { + *apic_id = gic->gic_id; + return 0; + } + + return -EINVAL; +} + static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; @@ -124,6 +127,9 @@ static int map_madt_entry(int type, u32 acpi_id) } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (!map_lsapic_id(header, type, acpi_id, &apic_id)) break; + } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { + if (!map_gic_id(header, type, acpi_id, &apic_id)) + break; } entry += header->length; } @@ -154,6 +160,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) map_lapic_id(header, acpi_id, &apic_id); } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { map_lsapic_id(header, type, acpi_id, &apic_id); + } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { + map_gic_id(header, type, acpi_id, &apic_id); } exit: @@ -323,7 +331,7 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int +static acpi_status acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; @@ -379,16 +387,43 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void __init acpi_early_processor_set_pdc(void) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) +static int __init set_no_mwait(const struct dmi_system_id *id) +{ + pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n", + id->ident); + boot_option_idle_override = IDLE_NOMWAIT; + return 0; +} + +static struct dmi_system_id processor_idle_dmi_table[] __initdata = { + { + set_no_mwait, "Extensa 5220", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, + {}, +}; + +static void __init processor_dmi_check(void) { /* * Check whether the system is DMI table. If yes, OSPM * should not use mwait for CPU-states. */ dmi_check_system(processor_idle_dmi_table); +} +#else +static inline void processor_dmi_check(void) {} +#endif + +void __init acpi_early_processor_set_pdc(void) +{ + processor_dmi_check(); acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); - acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL); + acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index c1c35623550f..7f70f3182d50 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -41,8 +41,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ff90054f04fd..cfc8aba72f86 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -156,17 +156,9 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) */ static void acpi_processor_ppc_ost(acpi_handle handle, int status) { - union acpi_object params[2] = { - {.type = ACPI_TYPE_INTEGER,}, - {.type = ACPI_TYPE_INTEGER,}, - }; - struct acpi_object_list arg_list = {2, params}; - - if (acpi_has_method(handle, "_OST")) { - params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; - params[1].integer.value = status; - acpi_evaluate_object(handle, "_OST", &arg_list, NULL); - } + if (acpi_has_method(handle, "_OST")) + acpi_evaluate_ost(handle, ACPI_PROCESSOR_NOTIFY_PERFORMANCE, + status, NULL); } int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index dbd48498b938..366ca40a6f70 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -37,12 +37,12 @@ #include <linux/power_supply.h> #include "sbshc.h" +#include "battery.h" #define PREFIX "ACPI: " #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" -#define ACPI_BATTERY_CLASS "battery" #define ACPI_SBS_DEVICE_NAME "Smart Battery System" #define ACPI_SBS_FILE_INFO "info" #define ACPI_SBS_FILE_STATE "state" diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 57b053f424d1..7efe546a8c42 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); +static DEFINE_MUTEX(acpi_hp_context_lock); struct acpi_device_bus_id{ char bus_id[15]; @@ -60,6 +61,27 @@ void acpi_scan_lock_release(void) } EXPORT_SYMBOL_GPL(acpi_scan_lock_release); +void acpi_lock_hp_context(void) +{ + mutex_lock(&acpi_hp_context_lock); +} + +void acpi_unlock_hp_context(void) +{ + mutex_unlock(&acpi_hp_context_lock); +} + +void acpi_initialize_hp_context(struct acpi_device *adev, + struct acpi_hotplug_context *hp, + int (*notify)(struct acpi_device *, u32), + void (*uevent)(struct acpi_device *, u32)) +{ + acpi_lock_hp_context(); + acpi_set_hp_context(adev, hp, notify, uevent, NULL); + acpi_unlock_hp_context(); +} +EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); + int acpi_scan_add_handler(struct acpi_scan_handler *handler) { if (!handler || !handler->attach) @@ -439,90 +461,75 @@ static int acpi_scan_bus_check(struct acpi_device *adev) return 0; } -static void acpi_device_hotplug(void *data, u32 src) +static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type) { - u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; - struct acpi_device *adev = data; - int error; - - lock_device_hotplug(); - mutex_lock(&acpi_scan_lock); - - /* - * 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; - - switch (src) { + switch (type) { case ACPI_NOTIFY_BUS_CHECK: - error = acpi_scan_bus_check(adev); - break; + return acpi_scan_bus_check(adev); case ACPI_NOTIFY_DEVICE_CHECK: - error = acpi_scan_device_check(adev); - break; + return acpi_scan_device_check(adev); case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_OST_EC_OSPM_EJECT: - error = acpi_scan_hot_remove(adev); - break; - default: - error = -EINVAL; - break; + if (adev->handler && !adev->handler->hotplug.enabled) { + dev_info(&adev->dev, "Eject disabled\n"); + return -EPERM; + } + acpi_evaluate_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); + return acpi_scan_hot_remove(adev); } - if (!error) - ost_code = ACPI_OST_SC_SUCCESS; - - out: - acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); - put_device(&adev->dev); - mutex_unlock(&acpi_scan_lock); - unlock_device_hotplug(); + return -EINVAL; } -static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) +void acpi_device_hotplug(struct acpi_device *adev, u32 src) { u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; - struct acpi_device *adev; - acpi_status status; + int error = -ENODEV; - if (acpi_bus_get_device(handle, &adev)) - goto err_out; + lock_device_hotplug(); + mutex_lock(&acpi_scan_lock); - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); - break; - case ACPI_NOTIFY_DEVICE_CHECK: - acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); - break; - case ACPI_NOTIFY_EJECT_REQUEST: - acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); - if (!adev->handler) - goto err_out; + /* + * The device object's ACPI handle cannot become invalid as long as we + * are holding acpi_scan_lock, but it might have become invalid before + * that lock was acquired. + */ + if (adev->handle == INVALID_ACPI_HANDLE) + goto err_out; - if (!adev->handler->hotplug.enabled) { - acpi_handle_err(handle, "Eject disabled\n"); + if (adev->flags.is_dock_station) { + error = dock_notify(adev, src); + } else if (adev->flags.hotplug_notify) { + error = acpi_generic_hotplug_event(adev, src); + if (error == -EPERM) { ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; 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; - } - get_device(&adev->dev); - status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); - if (ACPI_SUCCESS(status)) - return; + } else { + int (*notify)(struct acpi_device *, u32); - put_device(&adev->dev); + acpi_lock_hp_context(); + notify = adev->hp ? adev->hp->notify : NULL; + acpi_unlock_hp_context(); + /* + * There may be additional notify handlers for device objects + * without the .event() callback, so ignore them here. + */ + if (notify) + error = notify(adev, src); + else + goto out; + } + if (!error) + ost_code = ACPI_OST_SC_SUCCESS; err_out: - acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); + acpi_evaluate_ost(adev->handle, src, ost_code, NULL); + + out: + acpi_bus_put_acpi_device(adev); + mutex_unlock(&acpi_scan_lock); + unlock_device_hotplug(); } static ssize_t real_power_state_show(struct device *dev, @@ -570,17 +577,14 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) return -ENODEV; - 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_device_hotplug, acpi_device, - ACPI_OST_EC_OSPM_EJECT); + status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) return count; put_device(&acpi_device->dev); - acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); + acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, + ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; } @@ -1114,14 +1118,16 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context) mutex_unlock(&acpi_device_del_lock); } -int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) +static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device, + void (*callback)(void *)) { acpi_status status; if (!device) return -EINVAL; - status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); + status = acpi_get_data_full(handle, acpi_scan_drop_device, + (void **)device, callback); if (ACPI_FAILURE(status) || !*device) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", handle)); @@ -1129,8 +1135,32 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) } return 0; } + +int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) +{ + return acpi_get_device_data(handle, device, NULL); +} EXPORT_SYMBOL(acpi_bus_get_device); +static void get_acpi_device(void *dev) +{ + if (dev) + get_device(&((struct acpi_device *)dev)->dev); +} + +struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) +{ + struct acpi_device *adev = NULL; + + acpi_get_device_data(handle, &adev, get_acpi_device); + return adev; +} + +void acpi_bus_put_acpi_device(struct acpi_device *adev) +{ + put_device(&adev->dev); +} + int acpi_device_add(struct acpi_device *device, void (*release)(struct device *)) { @@ -1641,6 +1671,27 @@ bool acpi_bay_match(acpi_handle handle) return acpi_ata_match(phandle); } +bool acpi_device_is_battery(struct acpi_device *adev) +{ + struct acpi_hardware_id *hwid; + + list_for_each_entry(hwid, &adev->pnp.ids, list) + if (!strcmp("PNP0C0A", hwid->id)) + return true; + + return false; +} + +static bool is_ejectable_bay(struct acpi_device *adev) +{ + acpi_handle handle = adev->handle; + + if (acpi_has_method(handle, "_EJ0") && acpi_device_is_battery(adev)) + return true; + + return acpi_bay_match(handle); +} + /* * acpi_dock_match - see if an acpi object has a _DCK method */ @@ -1706,6 +1757,20 @@ static bool acpi_ibm_smbus_match(acpi_handle handle) return false; } +static bool acpi_object_is_system_bus(acpi_handle handle) +{ + acpi_handle tmp; + + if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_SB", &tmp)) && + tmp == handle) + return true; + if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_TZ", &tmp)) && + tmp == handle) + return true; + + return false; +} + static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, int device_type) { @@ -1757,8 +1822,10 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, acpi_add_id(pnp, ACPI_DOCK_HID); else if (acpi_ibm_smbus_match(handle)) acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); - else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) { - acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ + else if (list_empty(&pnp->ids) && + acpi_object_is_system_bus(handle)) { + /* \_SB, \_TZ, LNXSYBUS */ + acpi_add_id(pnp, ACPI_BUS_HID); strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME); strcpy(pnp->device_class, ACPI_BUS_CLASS); } @@ -1941,33 +2008,23 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val) mutex_unlock(&acpi_scan_lock); } -static void acpi_scan_init_hotplug(acpi_handle handle, int type) +static void acpi_scan_init_hotplug(struct acpi_device *adev) { - struct acpi_device_pnp pnp = {}; struct acpi_hardware_id *hwid; - struct acpi_scan_handler *handler; - INIT_LIST_HEAD(&pnp.ids); - acpi_set_pnp_ids(handle, &pnp, type); - - if (!pnp.type.hardware_id) - goto out; + if (acpi_dock_match(adev->handle) || is_ejectable_bay(adev)) { + acpi_dock_add(adev); + return; + } + list_for_each_entry(hwid, &adev->pnp.ids, list) { + struct acpi_scan_handler *handler; - /* - * This relies on the fact that acpi_install_notify_handler() will not - * install the same notify handler routine twice for the same handle. - */ - list_for_each_entry(hwid, &pnp.ids, list) { handler = acpi_scan_match_handler(hwid->id, NULL); if (handler) { - acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - acpi_hotplug_notify_cb, handler); + adev->flags.hotplug_notify = true; break; } } - -out: - acpi_free_pnp_ids(&pnp); } static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, @@ -1991,12 +2048,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_OK; } - acpi_scan_init_hotplug(handle, type); - acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; + acpi_scan_init_hotplug(device); + out: if (!*return_value) *return_value = device; @@ -2015,13 +2072,14 @@ static int acpi_scan_attach_handler(struct acpi_device *device) handler = acpi_scan_match_handler(hwid->id, &devid); if (handler) { + device->handler = handler; ret = handler->attach(device, devid); - if (ret > 0) { - device->handler = handler; + if (ret > 0) break; - } else if (ret < 0) { + + device->handler = NULL; + if (ret < 0) break; - } } } return ret; @@ -2030,8 +2088,12 @@ static int acpi_scan_attach_handler(struct acpi_device *device) static void acpi_bus_attach(struct acpi_device *device) { struct acpi_device *child; + acpi_handle ejd; int ret; + if (ACPI_SUCCESS(acpi_bus_get_ejd(device->handle, &ejd))) + register_dock_dependent_device(device, ejd); + acpi_bus_get_status(device); /* Skip devices that are not present. */ if (!acpi_device_is_present(device)) { @@ -2184,7 +2246,6 @@ int __init acpi_scan_init(void) acpi_cmos_rtc_init(); acpi_container_init(); acpi_memory_hotplug_init(); - acpi_dock_init(); mutex_lock(&acpi_scan_lock); /* diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 91a32cefb11f..38cb9782d4b8 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -12,8 +12,6 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("sysfs"); -#define PREFIX "ACPI: " - #ifdef CONFIG_ACPI_DEBUG /* * ACPI debug sysfs I/F, including: diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 5837f857ac2e..21782290df41 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -23,6 +23,8 @@ * */ +#define pr_fmt(fmt) "ACPI: " fmt + #include <linux/init.h> #include <linux/kernel.h> #include <linux/smp.h> @@ -33,8 +35,6 @@ #include <linux/acpi.h> #include <linux/bootmem.h> -#define PREFIX "ACPI: " - #define ACPI_MAX_TABLES 128 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; @@ -55,10 +55,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_local_apic *p = (struct acpi_madt_local_apic *)header; - printk(KERN_INFO PREFIX - "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", - p->processor_id, p->id, - (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + pr_info("LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", + p->processor_id, p->id, + (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); } break; @@ -66,11 +65,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_local_x2apic *p = (struct acpi_madt_local_x2apic *)header; - printk(KERN_INFO PREFIX - "X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n", - p->local_apic_id, p->uid, - (p->lapic_flags & ACPI_MADT_ENABLED) ? - "enabled" : "disabled"); + pr_info("X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n", + p->local_apic_id, p->uid, + (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); } break; @@ -78,9 +75,8 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_io_apic *p = (struct acpi_madt_io_apic *)header; - printk(KERN_INFO PREFIX - "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", - p->id, p->address, p->global_irq_base); + pr_info("IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", + p->id, p->address, p->global_irq_base); } break; @@ -88,18 +84,15 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_interrupt_override *p = (struct acpi_madt_interrupt_override *)header; - printk(KERN_INFO PREFIX - "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", - p->bus, p->source_irq, p->global_irq, - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]); + pr_info("INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", + p->bus, p->source_irq, p->global_irq, + mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], + mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]); if (p->inti_flags & ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)) - printk(KERN_INFO PREFIX - "INT_SRC_OVR unexpected reserved flags: 0x%x\n", - p->inti_flags & + pr_info("INT_SRC_OVR unexpected reserved flags: 0x%x\n", + p->inti_flags & ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)); - } break; @@ -107,11 +100,10 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_nmi_source *p = (struct acpi_madt_nmi_source *)header; - printk(KERN_INFO PREFIX - "NMI_SRC (%s %s global_irq %d)\n", - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], - p->global_irq); + pr_info("NMI_SRC (%s %s global_irq %d)\n", + mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], + mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], + p->global_irq); } break; @@ -119,12 +111,11 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_local_apic_nmi *p = (struct acpi_madt_local_apic_nmi *)header; - printk(KERN_INFO PREFIX - "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", - p->processor_id, - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK ], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], - p->lint); + pr_info("LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", + p->processor_id, + mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK ], + mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], + p->lint); } break; @@ -137,12 +128,11 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK; trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2; - printk(KERN_INFO PREFIX - "X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n", - p->uid, - mps_inti_flags_polarity[polarity], - mps_inti_flags_trigger[trigger], - p->lint); + pr_info("X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n", + p->uid, + mps_inti_flags_polarity[polarity], + mps_inti_flags_trigger[trigger], + p->lint); } break; @@ -150,9 +140,8 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_local_apic_override *p = (struct acpi_madt_local_apic_override *)header; - printk(KERN_INFO PREFIX - "LAPIC_ADDR_OVR (address[%p])\n", - (void *)(unsigned long)p->address); + pr_info("LAPIC_ADDR_OVR (address[%p])\n", + (void *)(unsigned long)p->address); } break; @@ -160,10 +149,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_io_sapic *p = (struct acpi_madt_io_sapic *)header; - printk(KERN_INFO PREFIX - "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", - p->id, (void *)(unsigned long)p->address, - p->global_irq_base); + pr_info("IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", + p->id, (void *)(unsigned long)p->address, + p->global_irq_base); } break; @@ -171,10 +159,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_local_sapic *p = (struct acpi_madt_local_sapic *)header; - printk(KERN_INFO PREFIX - "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", - p->processor_id, p->id, p->eid, - (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + pr_info("LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", + p->processor_id, p->id, p->eid, + (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); } break; @@ -182,19 +169,17 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { struct acpi_madt_interrupt_source *p = (struct acpi_madt_interrupt_source *)header; - printk(KERN_INFO PREFIX - "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], - p->type, p->id, p->eid, p->io_sapic_vector, - p->global_irq); + pr_info("PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", + mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], + mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], + p->type, p->id, p->eid, p->io_sapic_vector, + p->global_irq); } break; default: - printk(KERN_WARNING PREFIX - "Found unsupported MADT entry (type = 0x%x)\n", - header->type); + pr_warn("Found unsupported MADT entry (type = 0x%x)\n", + header->type); break; } } @@ -225,7 +210,7 @@ acpi_table_parse_entries(char *id, acpi_get_table_with_size(id, 0, &table_header, &tbl_size); if (!table_header) { - printk(KERN_WARNING PREFIX "%4.4s not present\n", id); + pr_warn("%4.4s not present\n", id); return -ENODEV; } @@ -248,7 +233,7 @@ acpi_table_parse_entries(char *id, * infinite loop. */ if (entry->length == 0) { - pr_err(PREFIX "[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); + pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); goto err; } @@ -256,8 +241,8 @@ acpi_table_parse_entries(char *id, ((unsigned long)entry + entry->length); } if (max_entries && count > max_entries) { - printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of " - "%i found\n", id, entry_id, count - max_entries, count); + pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", + id, entry_id, count - max_entries, count); } early_acpi_os_unmap_memory((char *)table_header, tbl_size); @@ -322,13 +307,11 @@ static void __init check_multiple_madt(void) acpi_get_table_with_size(ACPI_SIG_MADT, 2, &table, &tbl_size); if (table) { - printk(KERN_WARNING PREFIX - "BIOS bug: multiple APIC/MADT found," - " using %d\n", acpi_apic_instance); - printk(KERN_WARNING PREFIX - "If \"acpi_apic_instance=%d\" works better, " - "notify linux-acpi@vger.kernel.org\n", - acpi_apic_instance ? 0 : 2); + pr_warn("BIOS bug: multiple APIC/MADT found, using %d\n", + acpi_apic_instance); + pr_warn("If \"acpi_apic_instance=%d\" works better, " + "notify linux-acpi@vger.kernel.org\n", + acpi_apic_instance ? 0 : 2); early_acpi_os_unmap_memory(table, tbl_size); } else @@ -365,8 +348,7 @@ static int __init acpi_parse_apic_instance(char *str) acpi_apic_instance = simple_strtoul(str, NULL, 0); - printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n", - acpi_apic_instance); + pr_notice("Shall use APIC/MADT table %d\n", acpi_apic_instance); return 0; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 08626c851be7..964068553334 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -43,6 +43,7 @@ #include <linux/device.h> #include <linux/thermal.h> #include <linux/acpi.h> +#include <linux/workqueue.h> #include <asm/uaccess.h> #define PREFIX "ACPI: " @@ -90,6 +91,8 @@ static int psv; module_param(psv, int, 0644); MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); +static struct workqueue_struct *acpi_thermal_pm_queue; + static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_remove(struct acpi_device *device); static void acpi_thermal_notify(struct acpi_device *device, u32 event); @@ -101,11 +104,13 @@ static const struct acpi_device_id thermal_device_ids[] = { MODULE_DEVICE_TABLE(acpi, thermal_device_ids); #ifdef CONFIG_PM_SLEEP +static int acpi_thermal_suspend(struct device *dev); static int acpi_thermal_resume(struct device *dev); #else +#define acpi_thermal_suspend NULL #define acpi_thermal_resume NULL #endif -static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); +static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume); static struct acpi_driver acpi_thermal_driver = { .name = "thermal", @@ -186,6 +191,7 @@ struct acpi_thermal { struct thermal_zone_device *thermal_zone; int tz_enabled; int kelvin_offset; + struct work_struct thermal_check_work; }; /* -------------------------------------------------------------------------- @@ -1064,6 +1070,13 @@ static void acpi_thermal_guess_offset(struct acpi_thermal *tz) tz->kelvin_offset = 2732; } +static void acpi_thermal_check_fn(struct work_struct *work) +{ + struct acpi_thermal *tz = container_of(work, struct acpi_thermal, + thermal_check_work); + acpi_thermal_check(tz); +} + static int acpi_thermal_add(struct acpi_device *device) { int result = 0; @@ -1093,6 +1106,8 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto free_memory; + INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); + pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); goto end; @@ -1110,6 +1125,7 @@ static int acpi_thermal_remove(struct acpi_device *device) if (!device || !acpi_driver_data(device)) return -EINVAL; + flush_workqueue(acpi_thermal_pm_queue); tz = acpi_driver_data(device); acpi_thermal_unregister_thermal_zone(tz); @@ -1118,6 +1134,13 @@ static int acpi_thermal_remove(struct acpi_device *device) } #ifdef CONFIG_PM_SLEEP +static int acpi_thermal_suspend(struct device *dev) +{ + /* Make sure the previously queued thermal check work has been done */ + flush_workqueue(acpi_thermal_pm_queue); + return 0; +} + static int acpi_thermal_resume(struct device *dev) { struct acpi_thermal *tz; @@ -1148,7 +1171,7 @@ static int acpi_thermal_resume(struct device *dev) tz->state.active |= tz->trips.active[i].flags.enabled; } - acpi_thermal_check(tz); + queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work); return AE_OK; } @@ -1240,16 +1263,22 @@ static int __init acpi_thermal_init(void) return -ENODEV; } + acpi_thermal_pm_queue = create_workqueue("acpi_thermal_pm"); + if (!acpi_thermal_pm_queue) + return -ENODEV; + result = acpi_bus_register_driver(&acpi_thermal_driver); - if (result < 0) + if (result < 0) { + destroy_workqueue(acpi_thermal_pm_queue); return -ENODEV; + } return 0; } static void __exit acpi_thermal_exit(void) { - + destroy_workqueue(acpi_thermal_pm_queue); acpi_bus_unregister_driver(&acpi_thermal_driver); return; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 85e3b612bdc0..0f5f78fa6545 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -422,7 +422,7 @@ out: EXPORT_SYMBOL(acpi_get_physical_device_location); /** - * acpi_evaluate_hotplug_ost: Evaluate _OST for hotplug operations + * acpi_evaluate_ost: Evaluate _OST for hotplug operations * @handle: ACPI device handle * @source_event: source event code * @status_code: status code @@ -433,17 +433,15 @@ EXPORT_SYMBOL(acpi_get_physical_device_location); * When the platform does not support _OST, this function has no effect. */ acpi_status -acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, - u32 status_code, struct acpi_buffer *status_buf) +acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code, + struct acpi_buffer *status_buf) { -#ifdef ACPI_HOTPLUG_OST union acpi_object params[3] = { {.type = ACPI_TYPE_INTEGER,}, {.type = ACPI_TYPE_INTEGER,}, {.type = ACPI_TYPE_BUFFER,} }; struct acpi_object_list arg_list = {3, params}; - acpi_status status; params[0].integer.value = source_event; params[1].integer.value = status_code; @@ -455,13 +453,9 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, params[2].buffer.length = 0; } - status = acpi_evaluate_object(handle, "_OST", &arg_list, NULL); - return status; -#else - return AE_OK; -#endif + return acpi_evaluate_object(handle, "_OST", &arg_list, NULL); } -EXPORT_SYMBOL(acpi_evaluate_hotplug_ost); +EXPORT_SYMBOL(acpi_evaluate_ost); /** * acpi_handle_printk: Print message with ACPI prefix and object path diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b6ba88ed31ae..48c7e8af9c96 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -45,8 +45,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" #define ACPI_VIDEO_NOTIFY_SWITCH 0x80 diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 19080c8e2f2a..33e3db548a29 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -40,8 +40,6 @@ #include "internal.h" -#define PREFIX "ACPI: " - ACPI_MODULE_NAME("video"); #define _COMPONENT ACPI_VIDEO_COMPONENT diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index b4f7cc2522d9..97a14fe47de1 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -38,6 +38,16 @@ static void ata_acpi_clear_gtf(struct ata_device *dev) dev->gtf_cache = NULL; } +struct ata_acpi_hotplug_context { + struct acpi_hotplug_context hp; + union { + struct ata_port *ap; + struct ata_device *dev; + } data; +}; + +#define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data) + /** * ata_dev_acpi_handle - provide the acpi_handle for an ata_device * @dev: the acpi_handle returned will correspond to this device @@ -121,18 +131,17 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, ata_port_wait_eh(ap); } -static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) +static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event) { - struct ata_device *dev = data; - + struct ata_device *dev = ata_hotplug_data(adev->hp).dev; ata_acpi_handle_hotplug(dev->link->ap, dev, event); + return 0; } -static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) +static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event) { - struct ata_port *ap = data; - - ata_acpi_handle_hotplug(ap, NULL, event); + ata_acpi_handle_hotplug(ata_hotplug_data(adev->hp).ap, NULL, event); + return 0; } static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, @@ -154,31 +163,23 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, } } -static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event) { - ata_acpi_uevent(data, NULL, event); + ata_acpi_uevent(ata_hotplug_data(adev->hp).ap, NULL, event); } -static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event) { - struct ata_device *dev = data; + struct ata_device *dev = ata_hotplug_data(adev->hp).dev; ata_acpi_uevent(dev->link->ap, dev, event); } -static const struct acpi_dock_ops ata_acpi_dev_dock_ops = { - .handler = ata_acpi_dev_notify_dock, - .uevent = ata_acpi_dev_uevent, -}; - -static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { - .handler = ata_acpi_ap_notify_dock, - .uevent = ata_acpi_ap_uevent, -}; - /* bind acpi handle to pata port */ void ata_acpi_bind_port(struct ata_port *ap) { struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); + struct acpi_device *adev; + struct ata_acpi_hotplug_context *context; if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) return; @@ -188,9 +189,17 @@ void ata_acpi_bind_port(struct ata_port *ap) if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; - /* we might be on a docking station */ - register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev), - &ata_acpi_ap_dock_ops, ap, NULL, NULL); + adev = ACPI_COMPANION(&ap->tdev); + if (!adev || adev->hp) + return; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return; + + context->data.ap = ap; + acpi_initialize_hp_context(adev, &context->hp, ata_acpi_ap_notify_dock, + ata_acpi_ap_uevent); } void ata_acpi_bind_dev(struct ata_device *dev) @@ -198,7 +207,8 @@ void ata_acpi_bind_dev(struct ata_device *dev) struct ata_port *ap = dev->link->ap; struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); - struct acpi_device *parent; + struct acpi_device *parent, *adev; + struct ata_acpi_hotplug_context *context; u64 adr; /* @@ -221,9 +231,17 @@ void ata_acpi_bind_dev(struct ata_device *dev) } acpi_preset_companion(&dev->tdev, parent, adr); + adev = ACPI_COMPANION(&dev->tdev); + if (!adev || adev->hp) + return; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return; - register_hotplug_dock_device(ata_dev_acpi_handle(dev), - &ata_acpi_dev_dock_ops, dev, NULL, NULL); + context->data.dev = dev; + acpi_initialize_hp_context(adev, &context->hp, ata_acpi_dev_notify_dock, + ata_acpi_dev_uevent); } /** diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 2e58ebb1f6c0..1cb8544598d5 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,6 +1,5 @@ -obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o +obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o -obj-$(CONFIG_PM_RUNTIME) += runtime.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_OPP) += opp.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index bfb8955c406c..dc127e5dec4b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -42,7 +42,7 @@ struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \ if (!__retval && __elapsed > __td->field) { \ __td->field = __elapsed; \ - dev_warn(dev, name " latency exceeded, new value %lld ns\n", \ + dev_dbg(dev, name " latency exceeded, new value %lld ns\n", \ __elapsed); \ genpd->max_off_time_changed = true; \ __td->constraint_changed = true; \ diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1b41fca3d65a..86d5e4fb5b98 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -29,6 +29,7 @@ #include <linux/async.h> #include <linux/suspend.h> #include <trace/events/power.h> +#include <linux/cpufreq.h> #include <linux/cpuidle.h> #include <linux/timer.h> @@ -91,6 +92,8 @@ void device_pm_sleep_init(struct device *dev) { dev->power.is_prepared = false; dev->power.is_suspended = false; + dev->power.is_noirq_suspended = false; + dev->power.is_late_suspended = false; init_completion(&dev->power.completion); complete_all(&dev->power.completion); dev->power.wakeup = NULL; @@ -467,7 +470,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd) * The driver of @dev will not receive interrupts while this function is being * executed. */ -static int device_resume_noirq(struct device *dev, pm_message_t state) +static int device_resume_noirq(struct device *dev, pm_message_t state, bool async) { pm_callback_t callback = NULL; char *info = NULL; @@ -479,6 +482,11 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) if (dev->power.syscore) goto Out; + if (!dev->power.is_noirq_suspended) + goto Out; + + dpm_wait(dev->parent, async); + if (dev->pm_domain) { info = "noirq power domain "; callback = pm_noirq_op(&dev->pm_domain->ops, state); @@ -499,12 +507,32 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) } error = dpm_run_callback(callback, dev, state, info); + dev->power.is_noirq_suspended = false; Out: + complete_all(&dev->power.completion); TRACE_RESUME(error); return error; } +static bool is_async(struct device *dev) +{ + return dev->power.async_suspend && pm_async_enabled + && !pm_trace_is_enabled(); +} + +static void async_resume_noirq(void *data, async_cookie_t cookie) +{ + struct device *dev = (struct device *)data; + int error; + + error = device_resume_noirq(dev, pm_transition, true); + if (error) + pm_dev_err(dev, pm_transition, " async", error); + + put_device(dev); +} + /** * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices. * @state: PM transition of the system being carried out. @@ -514,29 +542,48 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) */ static void dpm_resume_noirq(pm_message_t state) { + struct device *dev; ktime_t starttime = ktime_get(); mutex_lock(&dpm_list_mtx); - while (!list_empty(&dpm_noirq_list)) { - struct device *dev = to_device(dpm_noirq_list.next); - int error; + pm_transition = state; + /* + * Advanced the async threads upfront, + * in case the starting of async threads is + * delayed by non-async resuming devices. + */ + list_for_each_entry(dev, &dpm_noirq_list, power.entry) { + reinit_completion(&dev->power.completion); + if (is_async(dev)) { + get_device(dev); + async_schedule(async_resume_noirq, dev); + } + } + + while (!list_empty(&dpm_noirq_list)) { + dev = to_device(dpm_noirq_list.next); get_device(dev); list_move_tail(&dev->power.entry, &dpm_late_early_list); mutex_unlock(&dpm_list_mtx); - error = device_resume_noirq(dev, state); - if (error) { - suspend_stats.failed_resume_noirq++; - dpm_save_failed_step(SUSPEND_RESUME_NOIRQ); - dpm_save_failed_dev(dev_name(dev)); - pm_dev_err(dev, state, " noirq", error); + if (!is_async(dev)) { + int error; + + error = device_resume_noirq(dev, state, false); + if (error) { + suspend_stats.failed_resume_noirq++; + dpm_save_failed_step(SUSPEND_RESUME_NOIRQ); + dpm_save_failed_dev(dev_name(dev)); + pm_dev_err(dev, state, " noirq", error); + } } mutex_lock(&dpm_list_mtx); put_device(dev); } mutex_unlock(&dpm_list_mtx); + async_synchronize_full(); dpm_show_time(starttime, state, "noirq"); resume_device_irqs(); cpuidle_resume(); @@ -549,7 +596,7 @@ static void dpm_resume_noirq(pm_message_t state) * * Runtime PM is disabled for @dev while this function is being executed. */ -static int device_resume_early(struct device *dev, pm_message_t state) +static int device_resume_early(struct device *dev, pm_message_t state, bool async) { pm_callback_t callback = NULL; char *info = NULL; @@ -561,6 +608,11 @@ static int device_resume_early(struct device *dev, pm_message_t state) if (dev->power.syscore) goto Out; + if (!dev->power.is_late_suspended) + goto Out; + + dpm_wait(dev->parent, async); + if (dev->pm_domain) { info = "early power domain "; callback = pm_late_early_op(&dev->pm_domain->ops, state); @@ -581,43 +633,75 @@ static int device_resume_early(struct device *dev, pm_message_t state) } error = dpm_run_callback(callback, dev, state, info); + dev->power.is_late_suspended = false; Out: TRACE_RESUME(error); pm_runtime_enable(dev); + complete_all(&dev->power.completion); return error; } +static void async_resume_early(void *data, async_cookie_t cookie) +{ + struct device *dev = (struct device *)data; + int error; + + error = device_resume_early(dev, pm_transition, true); + if (error) + pm_dev_err(dev, pm_transition, " async", error); + + put_device(dev); +} + /** * dpm_resume_early - Execute "early resume" callbacks for all devices. * @state: PM transition of the system being carried out. */ static void dpm_resume_early(pm_message_t state) { + struct device *dev; ktime_t starttime = ktime_get(); mutex_lock(&dpm_list_mtx); - while (!list_empty(&dpm_late_early_list)) { - struct device *dev = to_device(dpm_late_early_list.next); - int error; + pm_transition = state; + /* + * Advanced the async threads upfront, + * in case the starting of async threads is + * delayed by non-async resuming devices. + */ + list_for_each_entry(dev, &dpm_late_early_list, power.entry) { + reinit_completion(&dev->power.completion); + if (is_async(dev)) { + get_device(dev); + async_schedule(async_resume_early, dev); + } + } + + while (!list_empty(&dpm_late_early_list)) { + dev = to_device(dpm_late_early_list.next); get_device(dev); list_move_tail(&dev->power.entry, &dpm_suspended_list); mutex_unlock(&dpm_list_mtx); - error = device_resume_early(dev, state); - if (error) { - suspend_stats.failed_resume_early++; - dpm_save_failed_step(SUSPEND_RESUME_EARLY); - dpm_save_failed_dev(dev_name(dev)); - pm_dev_err(dev, state, " early", error); - } + if (!is_async(dev)) { + int error; + error = device_resume_early(dev, state, false); + if (error) { + suspend_stats.failed_resume_early++; + dpm_save_failed_step(SUSPEND_RESUME_EARLY); + dpm_save_failed_dev(dev_name(dev)); + pm_dev_err(dev, state, " early", error); + } + } mutex_lock(&dpm_list_mtx); put_device(dev); } mutex_unlock(&dpm_list_mtx); + async_synchronize_full(); dpm_show_time(starttime, state, "early"); } @@ -732,12 +816,6 @@ static void async_resume(void *data, async_cookie_t cookie) put_device(dev); } -static bool is_async(struct device *dev) -{ - return dev->power.async_suspend && pm_async_enabled - && !pm_trace_is_enabled(); -} - /** * dpm_resume - Execute "resume" callbacks for non-sysdev devices. * @state: PM transition of the system being carried out. @@ -789,6 +867,8 @@ void dpm_resume(pm_message_t state) mutex_unlock(&dpm_list_mtx); async_synchronize_full(); dpm_show_time(starttime, state, NULL); + + cpufreq_resume(); } /** @@ -913,13 +993,24 @@ static pm_message_t resume_event(pm_message_t sleep_state) * The driver of @dev will not receive interrupts while this function is being * executed. */ -static int device_suspend_noirq(struct device *dev, pm_message_t state) +static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async) { pm_callback_t callback = NULL; char *info = NULL; + int error = 0; + + if (async_error) + goto Complete; + + if (pm_wakeup_pending()) { + async_error = -EBUSY; + goto Complete; + } if (dev->power.syscore) - return 0; + goto Complete; + + dpm_wait_for_children(dev, async); if (dev->pm_domain) { info = "noirq power domain "; @@ -940,7 +1031,41 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) callback = pm_noirq_op(dev->driver->pm, state); } - return dpm_run_callback(callback, dev, state, info); + error = dpm_run_callback(callback, dev, state, info); + if (!error) + dev->power.is_noirq_suspended = true; + else + async_error = error; + +Complete: + complete_all(&dev->power.completion); + return error; +} + +static void async_suspend_noirq(void *data, async_cookie_t cookie) +{ + struct device *dev = (struct device *)data; + int error; + + error = __device_suspend_noirq(dev, pm_transition, true); + if (error) { + dpm_save_failed_dev(dev_name(dev)); + pm_dev_err(dev, pm_transition, " async", error); + } + + put_device(dev); +} + +static int device_suspend_noirq(struct device *dev) +{ + reinit_completion(&dev->power.completion); + + if (pm_async_enabled && dev->power.async_suspend) { + get_device(dev); + async_schedule(async_suspend_noirq, dev); + return 0; + } + return __device_suspend_noirq(dev, pm_transition, false); } /** @@ -958,19 +1083,20 @@ static int dpm_suspend_noirq(pm_message_t state) cpuidle_pause(); suspend_device_irqs(); mutex_lock(&dpm_list_mtx); + pm_transition = state; + async_error = 0; + while (!list_empty(&dpm_late_early_list)) { struct device *dev = to_device(dpm_late_early_list.prev); get_device(dev); mutex_unlock(&dpm_list_mtx); - error = device_suspend_noirq(dev, state); + error = device_suspend_noirq(dev); mutex_lock(&dpm_list_mtx); if (error) { pm_dev_err(dev, state, " noirq", error); - suspend_stats.failed_suspend_noirq++; - dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ); dpm_save_failed_dev(dev_name(dev)); put_device(dev); break; @@ -979,16 +1105,21 @@ static int dpm_suspend_noirq(pm_message_t state) list_move(&dev->power.entry, &dpm_noirq_list); put_device(dev); - if (pm_wakeup_pending()) { - error = -EBUSY; + if (async_error) break; - } } mutex_unlock(&dpm_list_mtx); - if (error) + async_synchronize_full(); + if (!error) + error = async_error; + + if (error) { + suspend_stats.failed_suspend_noirq++; + dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ); dpm_resume_noirq(resume_event(state)); - else + } else { dpm_show_time(starttime, state, "noirq"); + } return error; } @@ -999,15 +1130,26 @@ static int dpm_suspend_noirq(pm_message_t state) * * Runtime PM is disabled for @dev while this function is being executed. */ -static int device_suspend_late(struct device *dev, pm_message_t state) +static int __device_suspend_late(struct device *dev, pm_message_t state, bool async) { pm_callback_t callback = NULL; char *info = NULL; + int error = 0; __pm_runtime_disable(dev, false); + if (async_error) + goto Complete; + + if (pm_wakeup_pending()) { + async_error = -EBUSY; + goto Complete; + } + if (dev->power.syscore) - return 0; + goto Complete; + + dpm_wait_for_children(dev, async); if (dev->pm_domain) { info = "late power domain "; @@ -1028,7 +1170,41 @@ static int device_suspend_late(struct device *dev, pm_message_t state) callback = pm_late_early_op(dev->driver->pm, state); } - return dpm_run_callback(callback, dev, state, info); + error = dpm_run_callback(callback, dev, state, info); + if (!error) + dev->power.is_late_suspended = true; + else + async_error = error; + +Complete: + complete_all(&dev->power.completion); + return error; +} + +static void async_suspend_late(void *data, async_cookie_t cookie) +{ + struct device *dev = (struct device *)data; + int error; + + error = __device_suspend_late(dev, pm_transition, true); + if (error) { + dpm_save_failed_dev(dev_name(dev)); + pm_dev_err(dev, pm_transition, " async", error); + } + put_device(dev); +} + +static int device_suspend_late(struct device *dev) +{ + reinit_completion(&dev->power.completion); + + if (pm_async_enabled && dev->power.async_suspend) { + get_device(dev); + async_schedule(async_suspend_late, dev); + return 0; + } + + return __device_suspend_late(dev, pm_transition, false); } /** @@ -1041,19 +1217,20 @@ static int dpm_suspend_late(pm_message_t state) int error = 0; mutex_lock(&dpm_list_mtx); + pm_transition = state; + async_error = 0; + while (!list_empty(&dpm_suspended_list)) { struct device *dev = to_device(dpm_suspended_list.prev); get_device(dev); mutex_unlock(&dpm_list_mtx); - error = device_suspend_late(dev, state); + error = device_suspend_late(dev); mutex_lock(&dpm_list_mtx); if (error) { pm_dev_err(dev, state, " late", error); - suspend_stats.failed_suspend_late++; - dpm_save_failed_step(SUSPEND_SUSPEND_LATE); dpm_save_failed_dev(dev_name(dev)); put_device(dev); break; @@ -1062,17 +1239,18 @@ static int dpm_suspend_late(pm_message_t state) list_move(&dev->power.entry, &dpm_late_early_list); put_device(dev); - if (pm_wakeup_pending()) { - error = -EBUSY; + if (async_error) break; - } } mutex_unlock(&dpm_list_mtx); - if (error) + async_synchronize_full(); + if (error) { + suspend_stats.failed_suspend_late++; + dpm_save_failed_step(SUSPEND_SUSPEND_LATE); dpm_resume_early(resume_event(state)); - else + } else { dpm_show_time(starttime, state, "late"); - + } return error; } @@ -1259,6 +1437,8 @@ int dpm_suspend(pm_message_t state) might_sleep(); + cpufreq_suspend(); + mutex_lock(&dpm_list_mtx); pm_transition = state; async_error = 0; diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index cfc3226ec492..a21223d95926 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -89,8 +89,8 @@ extern void dpm_sysfs_remove(struct device *dev); extern void rpm_sysfs_remove(struct device *dev); extern int wakeup_sysfs_add(struct device *dev); extern void wakeup_sysfs_remove(struct device *dev); -extern int pm_qos_sysfs_add_latency(struct device *dev); -extern void pm_qos_sysfs_remove_latency(struct device *dev); +extern int pm_qos_sysfs_add_resume_latency(struct device *dev); +extern void pm_qos_sysfs_remove_resume_latency(struct device *dev); extern int pm_qos_sysfs_add_flags(struct device *dev); extern void pm_qos_sysfs_remove_flags(struct device *dev); diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 5c1361a9e5dd..36b9eb4862cb 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -105,7 +105,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags); s32 __dev_pm_qos_read_value(struct device *dev) { return IS_ERR_OR_NULL(dev->power.qos) ? - 0 : pm_qos_read_value(&dev->power.qos->latency); + 0 : pm_qos_read_value(&dev->power.qos->resume_latency); } /** @@ -141,16 +141,24 @@ static int apply_constraint(struct dev_pm_qos_request *req, int ret; switch(req->type) { - case DEV_PM_QOS_LATENCY: - ret = pm_qos_update_target(&qos->latency, &req->data.pnode, - action, value); + case DEV_PM_QOS_RESUME_LATENCY: + ret = pm_qos_update_target(&qos->resume_latency, + &req->data.pnode, action, value); if (ret) { - value = pm_qos_read_value(&qos->latency); + value = pm_qos_read_value(&qos->resume_latency); blocking_notifier_call_chain(&dev_pm_notifiers, (unsigned long)value, req); } break; + case DEV_PM_QOS_LATENCY_TOLERANCE: + ret = pm_qos_update_target(&qos->latency_tolerance, + &req->data.pnode, action, value); + if (ret) { + value = pm_qos_read_value(&qos->latency_tolerance); + req->dev->power.set_latency_tolerance(req->dev, value); + } + break; case DEV_PM_QOS_FLAGS: ret = pm_qos_update_flags(&qos->flags, &req->data.flr, action, value); @@ -186,13 +194,21 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) } BLOCKING_INIT_NOTIFIER_HEAD(n); - c = &qos->latency; + c = &qos->resume_latency; plist_head_init(&c->list); - c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; - c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; + c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; + c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; + c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; c->type = PM_QOS_MIN; c->notifiers = n; + c = &qos->latency_tolerance; + plist_head_init(&c->list); + c->target_value = PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE; + c->default_value = PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE; + c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; + c->type = PM_QOS_MIN; + INIT_LIST_HEAD(&qos->flags.list); spin_lock_irq(&dev->power.lock); @@ -224,7 +240,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) * If the device's PM QoS resume latency limit or PM QoS flags have been * exposed to user space, they have to be hidden at this point. */ - pm_qos_sysfs_remove_latency(dev); + pm_qos_sysfs_remove_resume_latency(dev); pm_qos_sysfs_remove_flags(dev); mutex_lock(&dev_pm_qos_mtx); @@ -237,7 +253,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) goto out; /* Flush the constraints lists for the device. */ - c = &qos->latency; + c = &qos->resume_latency; plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { /* * Update constraints list and call the notification @@ -246,6 +262,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev) apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); memset(req, 0, sizeof(*req)); } + c = &qos->latency_tolerance; + plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { + apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); + memset(req, 0, sizeof(*req)); + } f = &qos->flags; list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) { apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); @@ -265,6 +286,40 @@ void dev_pm_qos_constraints_destroy(struct device *dev) mutex_unlock(&dev_pm_qos_sysfs_mtx); } +static bool dev_pm_qos_invalid_request(struct device *dev, + struct dev_pm_qos_request *req) +{ + return !req || (req->type == DEV_PM_QOS_LATENCY_TOLERANCE + && !dev->power.set_latency_tolerance); +} + +static int __dev_pm_qos_add_request(struct device *dev, + struct dev_pm_qos_request *req, + enum dev_pm_qos_req_type type, s32 value) +{ + int ret = 0; + + if (!dev || dev_pm_qos_invalid_request(dev, req)) + return -EINVAL; + + if (WARN(dev_pm_qos_request_active(req), + "%s() called for already added request\n", __func__)) + return -EINVAL; + + if (IS_ERR(dev->power.qos)) + ret = -ENODEV; + else if (!dev->power.qos) + ret = dev_pm_qos_constraints_allocate(dev); + + trace_dev_pm_qos_add_request(dev_name(dev), type, value); + if (!ret) { + req->dev = dev; + req->type = type; + ret = apply_constraint(req, PM_QOS_ADD_REQ, value); + } + return ret; +} + /** * dev_pm_qos_add_request - inserts new qos request into the list * @dev: target device for the constraint @@ -290,31 +345,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev) int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, s32 value) { - int ret = 0; - - if (!dev || !req) /*guard against callers passing in null */ - return -EINVAL; - - if (WARN(dev_pm_qos_request_active(req), - "%s() called for already added request\n", __func__)) - return -EINVAL; + int ret; mutex_lock(&dev_pm_qos_mtx); - - if (IS_ERR(dev->power.qos)) - ret = -ENODEV; - else if (!dev->power.qos) - ret = dev_pm_qos_constraints_allocate(dev); - - trace_dev_pm_qos_add_request(dev_name(dev), type, value); - if (!ret) { - req->dev = dev; - req->type = type; - ret = apply_constraint(req, PM_QOS_ADD_REQ, value); - } - + ret = __dev_pm_qos_add_request(dev, req, type, value); mutex_unlock(&dev_pm_qos_mtx); - return ret; } EXPORT_SYMBOL_GPL(dev_pm_qos_add_request); @@ -341,7 +376,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, return -ENODEV; switch(req->type) { - case DEV_PM_QOS_LATENCY: + case DEV_PM_QOS_RESUME_LATENCY: + case DEV_PM_QOS_LATENCY_TOLERANCE: curr_value = req->data.pnode.prio; break; case DEV_PM_QOS_FLAGS: @@ -460,8 +496,8 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) ret = dev_pm_qos_constraints_allocate(dev); if (!ret) - ret = blocking_notifier_chain_register( - dev->power.qos->latency.notifiers, notifier); + ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers, + notifier); mutex_unlock(&dev_pm_qos_mtx); return ret; @@ -487,9 +523,8 @@ int dev_pm_qos_remove_notifier(struct device *dev, /* Silently return if the constraints object is not present. */ if (!IS_ERR_OR_NULL(dev->power.qos)) - retval = blocking_notifier_chain_unregister( - dev->power.qos->latency.notifiers, - notifier); + retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers, + notifier); mutex_unlock(&dev_pm_qos_mtx); return retval; @@ -530,20 +565,32 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier); * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor. * @dev: Device whose ancestor to add the request for. * @req: Pointer to the preallocated handle. + * @type: Type of the request. * @value: Constraint latency value. */ int dev_pm_qos_add_ancestor_request(struct device *dev, - struct dev_pm_qos_request *req, s32 value) + struct dev_pm_qos_request *req, + enum dev_pm_qos_req_type type, s32 value) { struct device *ancestor = dev->parent; int ret = -ENODEV; - while (ancestor && !ancestor->power.ignore_children) - ancestor = ancestor->parent; + switch (type) { + case DEV_PM_QOS_RESUME_LATENCY: + while (ancestor && !ancestor->power.ignore_children) + ancestor = ancestor->parent; + break; + case DEV_PM_QOS_LATENCY_TOLERANCE: + while (ancestor && !ancestor->power.set_latency_tolerance) + ancestor = ancestor->parent; + + break; + default: + ancestor = NULL; + } if (ancestor) - ret = dev_pm_qos_add_request(ancestor, req, - DEV_PM_QOS_LATENCY, value); + ret = dev_pm_qos_add_request(ancestor, req, type, value); if (ret < 0) req->dev = NULL; @@ -559,9 +606,13 @@ static void __dev_pm_qos_drop_user_request(struct device *dev, struct dev_pm_qos_request *req = NULL; switch(type) { - case DEV_PM_QOS_LATENCY: - req = dev->power.qos->latency_req; - dev->power.qos->latency_req = NULL; + case DEV_PM_QOS_RESUME_LATENCY: + req = dev->power.qos->resume_latency_req; + dev->power.qos->resume_latency_req = NULL; + break; + case DEV_PM_QOS_LATENCY_TOLERANCE: + req = dev->power.qos->latency_tolerance_req; + dev->power.qos->latency_tolerance_req = NULL; break; case DEV_PM_QOS_FLAGS: req = dev->power.qos->flags_req; @@ -597,7 +648,7 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) if (!req) return -ENOMEM; - ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); + ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_RESUME_LATENCY, value); if (ret < 0) { kfree(req); return ret; @@ -609,7 +660,7 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) if (IS_ERR_OR_NULL(dev->power.qos)) ret = -ENODEV; - else if (dev->power.qos->latency_req) + else if (dev->power.qos->resume_latency_req) ret = -EEXIST; if (ret < 0) { @@ -618,13 +669,13 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) mutex_unlock(&dev_pm_qos_mtx); goto out; } - dev->power.qos->latency_req = req; + dev->power.qos->resume_latency_req = req; mutex_unlock(&dev_pm_qos_mtx); - ret = pm_qos_sysfs_add_latency(dev); + ret = pm_qos_sysfs_add_resume_latency(dev); if (ret) - dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); + dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY); out: mutex_unlock(&dev_pm_qos_sysfs_mtx); @@ -634,8 +685,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); static void __dev_pm_qos_hide_latency_limit(struct device *dev) { - if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) - __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); + if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->resume_latency_req) + __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY); } /** @@ -646,7 +697,7 @@ void dev_pm_qos_hide_latency_limit(struct device *dev) { mutex_lock(&dev_pm_qos_sysfs_mtx); - pm_qos_sysfs_remove_latency(dev); + pm_qos_sysfs_remove_resume_latency(dev); mutex_lock(&dev_pm_qos_mtx); __dev_pm_qos_hide_latency_limit(dev); @@ -768,6 +819,67 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) pm_runtime_put(dev); return ret; } + +/** + * dev_pm_qos_get_user_latency_tolerance - Get user space latency tolerance. + * @dev: Device to obtain the user space latency tolerance for. + */ +s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev) +{ + s32 ret; + + mutex_lock(&dev_pm_qos_mtx); + ret = IS_ERR_OR_NULL(dev->power.qos) + || !dev->power.qos->latency_tolerance_req ? + PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT : + dev->power.qos->latency_tolerance_req->data.pnode.prio; + mutex_unlock(&dev_pm_qos_mtx); + return ret; +} + +/** + * dev_pm_qos_update_user_latency_tolerance - Update user space latency tolerance. + * @dev: Device to update the user space latency tolerance for. + * @val: New user space latency tolerance for @dev (negative values disable). + */ +int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val) +{ + int ret; + + mutex_lock(&dev_pm_qos_mtx); + + if (IS_ERR_OR_NULL(dev->power.qos) + || !dev->power.qos->latency_tolerance_req) { + struct dev_pm_qos_request *req; + + if (val < 0) { + ret = -EINVAL; + goto out; + } + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto out; + } + ret = __dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY_TOLERANCE, val); + if (ret < 0) { + kfree(req); + goto out; + } + dev->power.qos->latency_tolerance_req = req; + } else { + if (val < 0) { + __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY_TOLERANCE); + ret = 0; + } else { + ret = __dev_pm_qos_update_request(dev->power.qos->latency_tolerance_req, val); + } + } + + out: + mutex_unlock(&dev_pm_qos_mtx); + return ret; +} #else /* !CONFIG_PM_RUNTIME */ static void __dev_pm_qos_hide_latency_limit(struct device *dev) {} static void __dev_pm_qos_hide_flags(struct device *dev) {} diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 72e00e66ecc5..67c7938e430b 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -13,6 +13,43 @@ #include <trace/events/rpm.h> #include "power.h" +#define RPM_GET_CALLBACK(dev, cb) \ +({ \ + int (*__rpm_cb)(struct device *__d); \ + \ + if (dev->pm_domain) \ + __rpm_cb = dev->pm_domain->ops.cb; \ + else if (dev->type && dev->type->pm) \ + __rpm_cb = dev->type->pm->cb; \ + else if (dev->class && dev->class->pm) \ + __rpm_cb = dev->class->pm->cb; \ + else if (dev->bus && dev->bus->pm) \ + __rpm_cb = dev->bus->pm->cb; \ + else \ + __rpm_cb = NULL; \ + \ + if (!__rpm_cb && dev->driver && dev->driver->pm) \ + __rpm_cb = dev->driver->pm->cb; \ + \ + __rpm_cb; \ +}) + +static int (*rpm_get_suspend_cb(struct device *dev))(struct device *) +{ + return RPM_GET_CALLBACK(dev, runtime_suspend); +} + +static int (*rpm_get_resume_cb(struct device *dev))(struct device *) +{ + return RPM_GET_CALLBACK(dev, runtime_resume); +} + +#ifdef CONFIG_PM_RUNTIME +static int (*rpm_get_idle_cb(struct device *dev))(struct device *) +{ + return RPM_GET_CALLBACK(dev, runtime_idle); +} + static int rpm_resume(struct device *dev, int rpmflags); static int rpm_suspend(struct device *dev, int rpmflags); @@ -310,19 +347,7 @@ static int rpm_idle(struct device *dev, int rpmflags) dev->power.idle_notification = true; - if (dev->pm_domain) - callback = dev->pm_domain->ops.runtime_idle; - else if (dev->type && dev->type->pm) - callback = dev->type->pm->runtime_idle; - else if (dev->class && dev->class->pm) - callback = dev->class->pm->runtime_idle; - else if (dev->bus && dev->bus->pm) - callback = dev->bus->pm->runtime_idle; - else - callback = NULL; - - if (!callback && dev->driver && dev->driver->pm) - callback = dev->driver->pm->runtime_idle; + callback = rpm_get_idle_cb(dev); if (callback) retval = __rpm_callback(callback, dev); @@ -492,19 +517,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) __update_runtime_status(dev, RPM_SUSPENDING); - if (dev->pm_domain) - callback = dev->pm_domain->ops.runtime_suspend; - else if (dev->type && dev->type->pm) - callback = dev->type->pm->runtime_suspend; - else if (dev->class && dev->class->pm) - callback = dev->class->pm->runtime_suspend; - else if (dev->bus && dev->bus->pm) - callback = dev->bus->pm->runtime_suspend; - else - callback = NULL; - - if (!callback && dev->driver && dev->driver->pm) - callback = dev->driver->pm->runtime_suspend; + callback = rpm_get_suspend_cb(dev); retval = rpm_callback(callback, dev); if (retval) @@ -724,19 +737,7 @@ static int rpm_resume(struct device *dev, int rpmflags) __update_runtime_status(dev, RPM_RESUMING); - if (dev->pm_domain) - callback = dev->pm_domain->ops.runtime_resume; - else if (dev->type && dev->type->pm) - callback = dev->type->pm->runtime_resume; - else if (dev->class && dev->class->pm) - callback = dev->class->pm->runtime_resume; - else if (dev->bus && dev->bus->pm) - callback = dev->bus->pm->runtime_resume; - else - callback = NULL; - - if (!callback && dev->driver && dev->driver->pm) - callback = dev->driver->pm->runtime_resume; + callback = rpm_get_resume_cb(dev); retval = rpm_callback(callback, dev); if (retval) { @@ -1130,7 +1131,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_barrier); * @dev: Device to handle. * @check_resume: If set, check if there's a resume request for the device. * - * Increment power.disable_depth for the device and if was zero previously, + * Increment power.disable_depth for the device and if it was zero previously, * cancel all pending runtime PM requests for the device and wait for all * operations in progress to complete. The device can be either active or * suspended after its runtime PM has been disabled. @@ -1401,3 +1402,86 @@ void pm_runtime_remove(struct device *dev) if (dev->power.irq_safe && dev->parent) pm_runtime_put(dev->parent); } +#endif + +/** + * pm_runtime_force_suspend - Force a device into suspend state if needed. + * @dev: Device to suspend. + * + * Disable runtime PM so we safely can check the device's runtime PM status and + * if it is active, invoke it's .runtime_suspend callback to bring it into + * suspend state. Keep runtime PM disabled to preserve the state unless we + * encounter errors. + * + * Typically this function may be invoked from a system suspend callback to make + * sure the device is put into low power state. + */ +int pm_runtime_force_suspend(struct device *dev) +{ + int (*callback)(struct device *); + int ret = 0; + + pm_runtime_disable(dev); + + /* + * Note that pm_runtime_status_suspended() returns false while + * !CONFIG_PM_RUNTIME, which means the device will be put into low + * power state. + */ + if (pm_runtime_status_suspended(dev)) + return 0; + + callback = rpm_get_suspend_cb(dev); + + if (!callback) { + ret = -ENOSYS; + goto err; + } + + ret = callback(dev); + if (ret) + goto err; + + pm_runtime_set_suspended(dev); + return 0; +err: + pm_runtime_enable(dev); + return ret; +} +EXPORT_SYMBOL_GPL(pm_runtime_force_suspend); + +/** + * pm_runtime_force_resume - Force a device into resume state. + * @dev: Device to resume. + * + * Prior invoking this function we expect the user to have brought the device + * into low power state by a call to pm_runtime_force_suspend(). Here we reverse + * those actions and brings the device into full power. We update the runtime PM + * status and re-enables runtime PM. + * + * Typically this function may be invoked from a system resume callback to make + * sure the device is put into full power state. + */ +int pm_runtime_force_resume(struct device *dev) +{ + int (*callback)(struct device *); + int ret = 0; + + callback = rpm_get_resume_cb(dev); + + if (!callback) { + ret = -ENOSYS; + goto out; + } + + ret = callback(dev); + if (ret) + goto out; + + pm_runtime_set_active(dev); + pm_runtime_mark_last_busy(dev); +out: + pm_runtime_enable(dev); + return ret; +} +EXPORT_SYMBOL_GPL(pm_runtime_force_resume); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 03e089ade5ce..95b181d1ca6d 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -218,15 +218,16 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev, static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show, autosuspend_delay_ms_store); -static ssize_t pm_qos_latency_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pm_qos_resume_latency_show(struct device *dev, + struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev)); + return sprintf(buf, "%d\n", dev_pm_qos_requested_resume_latency(dev)); } -static ssize_t pm_qos_latency_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t n) +static ssize_t pm_qos_resume_latency_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t n) { s32 value; int ret; @@ -237,12 +238,47 @@ static ssize_t pm_qos_latency_store(struct device *dev, if (value < 0) return -EINVAL; - ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value); + ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req, + value); return ret < 0 ? ret : n; } static DEVICE_ATTR(pm_qos_resume_latency_us, 0644, - pm_qos_latency_show, pm_qos_latency_store); + pm_qos_resume_latency_show, pm_qos_resume_latency_store); + +static ssize_t pm_qos_latency_tolerance_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + s32 value = dev_pm_qos_get_user_latency_tolerance(dev); + + if (value < 0) + return sprintf(buf, "auto\n"); + else if (value == PM_QOS_LATENCY_ANY) + return sprintf(buf, "any\n"); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t pm_qos_latency_tolerance_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + s32 value; + int ret; + + if (kstrtos32(buf, 0, &value)) { + if (!strcmp(buf, "auto") || !strcmp(buf, "auto\n")) + value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; + else if (!strcmp(buf, "any") || !strcmp(buf, "any\n")) + value = PM_QOS_LATENCY_ANY; + } + ret = dev_pm_qos_update_user_latency_tolerance(dev, value); + return ret < 0 ? ret : n; +} + +static DEVICE_ATTR(pm_qos_latency_tolerance_us, 0644, + pm_qos_latency_tolerance_show, pm_qos_latency_tolerance_store); static ssize_t pm_qos_no_power_off_show(struct device *dev, struct device_attribute *attr, @@ -618,15 +654,26 @@ static struct attribute_group pm_runtime_attr_group = { .attrs = runtime_attrs, }; -static struct attribute *pm_qos_latency_attrs[] = { +static struct attribute *pm_qos_resume_latency_attrs[] = { #ifdef CONFIG_PM_RUNTIME &dev_attr_pm_qos_resume_latency_us.attr, #endif /* CONFIG_PM_RUNTIME */ NULL, }; -static struct attribute_group pm_qos_latency_attr_group = { +static struct attribute_group pm_qos_resume_latency_attr_group = { + .name = power_group_name, + .attrs = pm_qos_resume_latency_attrs, +}; + +static struct attribute *pm_qos_latency_tolerance_attrs[] = { +#ifdef CONFIG_PM_RUNTIME + &dev_attr_pm_qos_latency_tolerance_us.attr, +#endif /* CONFIG_PM_RUNTIME */ + NULL, +}; +static struct attribute_group pm_qos_latency_tolerance_attr_group = { .name = power_group_name, - .attrs = pm_qos_latency_attrs, + .attrs = pm_qos_latency_tolerance_attrs, }; static struct attribute *pm_qos_flags_attrs[] = { @@ -654,18 +701,23 @@ int dpm_sysfs_add(struct device *dev) if (rc) goto err_out; } - if (device_can_wakeup(dev)) { rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); - if (rc) { - if (pm_runtime_callbacks_present(dev)) - sysfs_unmerge_group(&dev->kobj, - &pm_runtime_attr_group); - goto err_out; - } + if (rc) + goto err_runtime; + } + if (dev->power.set_latency_tolerance) { + rc = sysfs_merge_group(&dev->kobj, + &pm_qos_latency_tolerance_attr_group); + if (rc) + goto err_wakeup; } return 0; + err_wakeup: + sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); + err_runtime: + sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); err_out: sysfs_remove_group(&dev->kobj, &pm_attr_group); return rc; @@ -681,14 +733,14 @@ void wakeup_sysfs_remove(struct device *dev) sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); } -int pm_qos_sysfs_add_latency(struct device *dev) +int pm_qos_sysfs_add_resume_latency(struct device *dev) { - return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group); + return sysfs_merge_group(&dev->kobj, &pm_qos_resume_latency_attr_group); } -void pm_qos_sysfs_remove_latency(struct device *dev) +void pm_qos_sysfs_remove_resume_latency(struct device *dev) { - sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group); + sysfs_unmerge_group(&dev->kobj, &pm_qos_resume_latency_attr_group); } int pm_qos_sysfs_add_flags(struct device *dev) @@ -708,6 +760,7 @@ void rpm_sysfs_remove(struct device *dev) void dpm_sysfs_remove(struct device *dev) { + sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); dev_pm_qos_constraints_destroy(dev); rpm_sysfs_remove(dev); sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 31297499a60a..9fb627046e17 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -2,6 +2,7 @@ # ARM CPU Frequency scaling drivers # +# big LITTLE core layer and glue drivers config ARM_BIG_LITTLE_CPUFREQ tristate "Generic ARM big LITTLE CPUfreq driver" depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK @@ -16,6 +17,14 @@ config ARM_DT_BL_CPUFREQ This enables probing via DT for Generic CPUfreq driver for ARM big.LITTLE platform. This gets frequency tables from DT. +config ARM_VEXPRESS_SPC_CPUFREQ + tristate "Versatile Express SPC based CPUfreq driver" + depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC + help + This add the CPUfreq driver support for Versatile Express + big.LITTLE platforms using SPC for power management. + + config ARM_EXYNOS_CPUFREQ bool @@ -241,11 +250,3 @@ config ARM_TEGRA_CPUFREQ default y help This adds the CPUFreq driver support for TEGRA SOCs. - -config ARM_VEXPRESS_SPC_CPUFREQ - tristate "Versatile Express SPC based CPUfreq driver" - select ARM_BIG_LITTLE_CPUFREQ - depends on ARCH_VEXPRESS_SPC - help - This add the CPUfreq driver support for Versatile Express - big.LITTLE platforms using SPC for power management. diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 18448a7e9f86..822ca03a87f7 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) pr_debug("acpi_cpufreq_cpu_exit\n"); if (data) { - cpufreq_frequency_table_put_attr(policy->cpu); per_cpu(acfreq_data, policy->cpu) = NULL; acpi_processor_unregister_performance(data->acpi_data, policy->cpu); diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 72f87e9317e3..bad2ed317ba2 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -446,9 +446,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) } if (cur_cluster < MAX_CLUSTERS) { + int cpu; + cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); - per_cpu(physical_cluster, policy->cpu) = cur_cluster; + for_each_cpu(cpu, policy->cpus) + per_cpu(physical_cluster, cpu) = cur_cluster; } else { /* Assumption: during init, we are always running on A15 */ per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER; @@ -478,7 +481,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) return -ENODEV; } - cpufreq_frequency_table_put_attr(policy->cpu); put_cluster_clk_and_freq_table(cpu_dev); dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu); diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index e9e63fc9c2c9..a9f8e5bd0716 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = { .target_index = bfin_target, .get = bfin_getfreq_khz, .init = __bfin_cpu_init, - .exit = cpufreq_generic_exit, .name = "bfin cpufreq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 0c12ffc0ebcb..1bf6bbac3e03 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = { .target_index = cpu0_set_target, .get = cpufreq_generic_get, .init = cpu0_cpufreq_init, - .exit = cpufreq_generic_exit, .name = "generic_cpu0", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 199b52b7c3e1..3aa7a7a226b3 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -26,7 +26,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/syscore_ops.h> +#include <linux/suspend.h> #include <linux/tick.h> #include <trace/events/power.h> @@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock); DEFINE_MUTEX(cpufreq_governor_lock); static LIST_HEAD(cpufreq_policy_list); -#ifdef CONFIG_HOTPLUG_CPU /* This one keeps track of the previously set governor of a removed CPU */ static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); -#endif + +/* Flag to suspend/resume CPUFreq governors */ +static bool cpufreq_suspended; static inline bool has_target(void) { @@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu) struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); if (!policy || IS_ERR(policy->clk)) { - pr_err("%s: No %s associated to cpu: %d\n", __func__, - policy ? "clk" : "policy", cpu); + pr_err("%s: No %s associated to cpu: %d\n", + __func__, policy ? "clk" : "policy", cpu); return 0; } @@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu) } EXPORT_SYMBOL_GPL(cpufreq_generic_get); +/* Only for cpufreq core internal use */ +struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu) +{ + return per_cpu(cpufreq_cpu_data, cpu); +} + struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { struct cpufreq_policy *policy = NULL; @@ -254,15 +261,14 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) if (!l_p_j_ref_freq) { l_p_j_ref = loops_per_jiffy; l_p_j_ref_freq = ci->old; - pr_debug("saving %lu as reference value for loops_per_jiffy; " - "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); + pr_debug("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", + l_p_j_ref, l_p_j_ref_freq); } - if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) || - (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { + if (val == CPUFREQ_POSTCHANGE && ci->old != ci->new) { loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); - pr_debug("scaling loops_per_jiffy to %lu " - "for frequency %u kHz\n", loops_per_jiffy, ci->new); + pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n", + loops_per_jiffy, ci->new); } } #else @@ -282,7 +288,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, freqs->flags = cpufreq_driver->flags; pr_debug("notification %u of frequency transition to %u kHz\n", - state, freqs->new); + state, freqs->new); switch (state) { @@ -294,9 +300,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if ((policy) && (policy->cpu == freqs->cpu) && (policy->cur) && (policy->cur != freqs->old)) { - pr_debug("Warning: CPU frequency is" - " %u, cpufreq assumed %u kHz.\n", - freqs->old, policy->cur); + pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n", + freqs->old, policy->cur); freqs->old = policy->cur; } } @@ -307,8 +312,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, case CPUFREQ_POSTCHANGE: adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); - pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, - (unsigned long)freqs->cpu); + pr_debug("FREQ: %lu - CPU: %lu\n", + (unsigned long)freqs->new, (unsigned long)freqs->cpu); trace_cpu_frequency(freqs->new, freqs->cpu); srcu_notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); @@ -352,7 +357,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); /********************************************************************* * SYSFS INTERFACE * *********************************************************************/ -ssize_t show_boost(struct kobject *kobj, +static ssize_t show_boost(struct kobject *kobj, struct attribute *attr, char *buf) { return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); @@ -368,13 +373,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, return -EINVAL; if (cpufreq_boost_trigger_state(enable)) { - pr_err("%s: Cannot %s BOOST!\n", __func__, - enable ? "enable" : "disable"); + pr_err("%s: Cannot %s BOOST!\n", + __func__, enable ? "enable" : "disable"); return -EINVAL; } - pr_debug("%s: cpufreq BOOST %s\n", __func__, - enable ? "enabled" : "disabled"); + pr_debug("%s: cpufreq BOOST %s\n", + __func__, enable ? "enabled" : "disabled"); return count; } @@ -879,18 +884,25 @@ err_out_kobj_put: static void cpufreq_init_policy(struct cpufreq_policy *policy) { + struct cpufreq_governor *gov = NULL; struct cpufreq_policy new_policy; int ret = 0; memcpy(&new_policy, policy, sizeof(*policy)); + /* Update governor of new_policy to the governor used before hotplug */ + gov = __find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu)); + if (gov) + pr_debug("Restoring governor %s for cpu %d\n", + policy->governor->name, policy->cpu); + else + gov = CPUFREQ_DEFAULT_GOVERNOR; + + new_policy.governor = gov; + /* Use the default policy if its valid. */ if (cpufreq_driver->setpolicy) - cpufreq_parse_governor(policy->governor->name, - &new_policy.policy, NULL); - - /* assure that the starting sequence is run in cpufreq_set_policy */ - policy->governor = NULL; + cpufreq_parse_governor(gov->name, &new_policy.policy, NULL); /* set default policy */ ret = cpufreq_set_policy(policy, &new_policy); @@ -927,8 +939,11 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, up_write(&policy->rwsem); if (has_target()) { - if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || - (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { + ret = __cpufreq_governor(policy, CPUFREQ_GOV_START); + if (!ret) + ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + + if (ret) { pr_err("%s: Failed to start governor\n", __func__); return ret; } @@ -949,6 +964,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) read_unlock_irqrestore(&cpufreq_driver_lock, flags); + policy->governor = NULL; + return policy; } @@ -1022,21 +1039,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) up_write(&policy->rwsem); - cpufreq_frequency_table_update_policy_cpu(policy); blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_UPDATE_POLICY_CPU, policy); } -static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, - bool frozen) +static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) { unsigned int j, cpu = dev->id; int ret = -ENOMEM; struct cpufreq_policy *policy; unsigned long flags; + bool recover_policy = cpufreq_suspended; #ifdef CONFIG_HOTPLUG_CPU struct cpufreq_policy *tpolicy; - struct cpufreq_governor *gov; #endif if (cpu_is_offline(cpu)) @@ -1075,9 +1090,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, * Restore the saved policy when doing light-weight init and fall back * to the full init if that fails. */ - policy = frozen ? cpufreq_policy_restore(cpu) : NULL; + policy = recover_policy ? cpufreq_policy_restore(cpu) : NULL; if (!policy) { - frozen = false; + recover_policy = false; policy = cpufreq_policy_alloc(); if (!policy) goto nomem_out; @@ -1089,12 +1104,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, * the creation of a brand new one. So we need to perform this update * by invoking update_policy_cpu(). */ - if (frozen && cpu != policy->cpu) + if (recover_policy && cpu != policy->cpu) update_policy_cpu(policy, cpu); else policy->cpu = cpu; - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; cpumask_copy(policy->cpus, cpumask_of(cpu)); init_completion(&policy->kobj_unregister); @@ -1118,7 +1132,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, */ cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); - if (!frozen) { + if (!recover_policy) { policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; } @@ -1180,16 +1194,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_START, policy); -#ifdef CONFIG_HOTPLUG_CPU - gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu)); - if (gov) { - policy->governor = gov; - pr_debug("Restoring governor %s for cpu %d\n", - policy->governor->name, cpu); - } -#endif - - if (!frozen) { + if (!recover_policy) { ret = cpufreq_add_dev_interface(policy, dev); if (ret) goto err_out_unregister; @@ -1203,7 +1208,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, cpufreq_init_policy(policy); - if (!frozen) { + if (!recover_policy) { policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; } @@ -1226,7 +1231,7 @@ err_get_freq: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); err_set_policy_cpu: - if (frozen) { + if (recover_policy) { /* Do not leave stale fallback data behind. */ per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL; cpufreq_policy_put_kobj(policy); @@ -1250,7 +1255,7 @@ nomem_out: */ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) { - return __cpufreq_add_dev(dev, sif, false); + return __cpufreq_add_dev(dev, sif); } static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, @@ -1265,7 +1270,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); ret = kobject_move(&policy->kobj, &cpu_dev->kobj); if (ret) { - pr_err("%s: Failed to move kobj: %d", __func__, ret); + pr_err("%s: Failed to move kobj: %d\n", __func__, ret); down_write(&policy->rwsem); cpumask_set_cpu(old_cpu, policy->cpus); @@ -1281,8 +1286,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, } static int __cpufreq_remove_dev_prepare(struct device *dev, - struct subsys_interface *sif, - bool frozen) + struct subsys_interface *sif) { unsigned int cpu = dev->id, cpus; int new_cpu, ret; @@ -1296,7 +1300,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, policy = per_cpu(cpufreq_cpu_data, cpu); /* Save the policy somewhere when doing a light-weight tear-down */ - if (frozen) + if (cpufreq_suspended) per_cpu(cpufreq_cpu_data_fallback, cpu) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -1314,11 +1318,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, } } -#ifdef CONFIG_HOTPLUG_CPU if (!cpufreq_driver->setpolicy) strncpy(per_cpu(cpufreq_cpu_governor, cpu), policy->governor->name, CPUFREQ_NAME_LEN); -#endif down_read(&policy->rwsem); cpus = cpumask_weight(policy->cpus); @@ -1331,19 +1333,19 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, if (new_cpu >= 0) { update_policy_cpu(policy, new_cpu); - if (!frozen) { + if (!cpufreq_suspended) pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", - __func__, new_cpu, cpu); - } + __func__, new_cpu, cpu); } + } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) { + cpufreq_driver->stop_cpu(policy); } return 0; } static int __cpufreq_remove_dev_finish(struct device *dev, - struct subsys_interface *sif, - bool frozen) + struct subsys_interface *sif) { unsigned int cpu = dev->id, cpus; int ret; @@ -1373,12 +1375,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev, CPUFREQ_GOV_POLICY_EXIT); if (ret) { pr_err("%s: Failed to exit governor\n", - __func__); + __func__); return ret; } } - if (!frozen) + if (!cpufreq_suspended) cpufreq_policy_put_kobj(policy); /* @@ -1394,16 +1396,16 @@ static int __cpufreq_remove_dev_finish(struct device *dev, list_del(&policy->policy_list); write_unlock_irqrestore(&cpufreq_driver_lock, flags); - if (!frozen) + if (!cpufreq_suspended) cpufreq_policy_free(policy); - } else { - if (has_target()) { - if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || - (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { - pr_err("%s: Failed to start governor\n", - __func__); - return ret; - } + } else if (has_target()) { + ret = __cpufreq_governor(policy, CPUFREQ_GOV_START); + if (!ret) + ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + + if (ret) { + pr_err("%s: Failed to start governor\n", __func__); + return ret; } } @@ -1424,10 +1426,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) if (cpu_is_offline(cpu)) return 0; - ret = __cpufreq_remove_dev_prepare(dev, sif, false); + ret = __cpufreq_remove_dev_prepare(dev, sif); if (!ret) - ret = __cpufreq_remove_dev_finish(dev, sif, false); + ret = __cpufreq_remove_dev_finish(dev, sif); return ret; } @@ -1458,8 +1460,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, struct cpufreq_freqs freqs; unsigned long flags; - pr_debug("Warning: CPU frequency out of sync: cpufreq and timing " - "core thinks of %u, is %u kHz.\n", old_freq, new_freq); + pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n", + old_freq, new_freq); freqs.old = old_freq; freqs.new = new_freq; @@ -1570,83 +1572,104 @@ static struct subsys_interface cpufreq_interface = { .remove_dev = cpufreq_remove_dev, }; +/* + * In case platform wants some specific frequency to be configured + * during suspend.. + */ +int cpufreq_generic_suspend(struct cpufreq_policy *policy) +{ + int ret; + + if (!policy->suspend_freq) { + pr_err("%s: suspend_freq can't be zero\n", __func__); + return -EINVAL; + } + + pr_debug("%s: Setting suspend-freq: %u\n", __func__, + policy->suspend_freq); + + ret = __cpufreq_driver_target(policy, policy->suspend_freq, + CPUFREQ_RELATION_H); + if (ret) + pr_err("%s: unable to set suspend-freq: %u. err: %d\n", + __func__, policy->suspend_freq, ret); + + return ret; +} +EXPORT_SYMBOL(cpufreq_generic_suspend); + /** - * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. + * cpufreq_suspend() - Suspend CPUFreq governors * - * This function is only executed for the boot processor. The other CPUs - * have been put offline by means of CPU hotplug. + * Called during system wide Suspend/Hibernate cycles for suspending governors + * as some platforms can't change frequency after this point in suspend cycle. + * Because some of the devices (like: i2c, regulators, etc) they use for + * changing frequency are suspended quickly after this point. */ -static int cpufreq_bp_suspend(void) +void cpufreq_suspend(void) { - int ret = 0; - - int cpu = smp_processor_id(); struct cpufreq_policy *policy; - pr_debug("suspending cpu %u\n", cpu); + if (!cpufreq_driver) + return; - /* If there's no policy for the boot CPU, we have nothing to do. */ - policy = cpufreq_cpu_get(cpu); - if (!policy) - return 0; + if (!has_target()) + return; - if (cpufreq_driver->suspend) { - ret = cpufreq_driver->suspend(policy); - if (ret) - printk(KERN_ERR "cpufreq: suspend failed in ->suspend " - "step on CPU %u\n", policy->cpu); + pr_debug("%s: Suspending Governors\n", __func__); + + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { + if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) + pr_err("%s: Failed to stop governor for policy: %p\n", + __func__, policy); + else if (cpufreq_driver->suspend + && cpufreq_driver->suspend(policy)) + pr_err("%s: Failed to suspend driver: %p\n", __func__, + policy); } - cpufreq_cpu_put(policy); - return ret; + cpufreq_suspended = true; } /** - * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. + * cpufreq_resume() - Resume CPUFreq governors * - * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) - * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are - * restored. It will verify that the current freq is in sync with - * what we believe it to be. This is a bit later than when it - * should be, but nonethteless it's better than calling - * cpufreq_driver->get() here which might re-enable interrupts... - * - * This function is only executed for the boot CPU. The other CPUs have not - * been turned on yet. + * Called during system wide Suspend/Hibernate cycle for resuming governors that + * are suspended with cpufreq_suspend(). */ -static void cpufreq_bp_resume(void) +void cpufreq_resume(void) { - int ret = 0; - - int cpu = smp_processor_id(); struct cpufreq_policy *policy; - pr_debug("resuming cpu %u\n", cpu); + if (!cpufreq_driver) + return; - /* If there's no policy for the boot CPU, we have nothing to do. */ - policy = cpufreq_cpu_get(cpu); - if (!policy) + if (!has_target()) return; - if (cpufreq_driver->resume) { - ret = cpufreq_driver->resume(policy); - if (ret) { - printk(KERN_ERR "cpufreq: resume failed in ->resume " - "step on CPU %u\n", policy->cpu); - goto fail; - } - } + pr_debug("%s: Resuming Governors\n", __func__); - schedule_work(&policy->update); + cpufreq_suspended = false; -fail: - cpufreq_cpu_put(policy); -} + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { + if (__cpufreq_governor(policy, CPUFREQ_GOV_START) + || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) + pr_err("%s: Failed to start governor for policy: %p\n", + __func__, policy); + else if (cpufreq_driver->resume + && cpufreq_driver->resume(policy)) + pr_err("%s: Failed to resume driver: %p\n", __func__, + policy); -static struct syscore_ops cpufreq_syscore_ops = { - .suspend = cpufreq_bp_suspend, - .resume = cpufreq_bp_resume, -}; + /* + * schedule call cpufreq_update_policy() for boot CPU, i.e. last + * policy in list. It will verify that the current freq is in + * sync with what we believe it to be. + */ + if (list_is_last(&policy->policy_list, &cpufreq_policy_list)) + schedule_work(&policy->update); + } +} /** * cpufreq_get_current_driver - return current driver's name @@ -1762,7 +1785,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, target_freq = policy->min; pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", - policy->cpu, target_freq, relation, old_target_freq); + policy->cpu, target_freq, relation, old_target_freq); /* * This might look like a redundant call as we are checking it again @@ -1807,8 +1830,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, freqs.flags = 0; pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", - __func__, policy->cpu, freqs.old, - freqs.new); + __func__, policy->cpu, freqs.old, freqs.new); cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); @@ -1817,7 +1839,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, retval = cpufreq_driver->target_index(policy, index); if (retval) pr_err("%s: Failed to change cpu frequency: %d\n", - __func__, retval); + __func__, retval); if (notify) cpufreq_notify_post_transition(policy, &freqs, retval); @@ -1863,17 +1885,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, struct cpufreq_governor *gov = NULL; #endif + /* Don't start any governor operations if we are entering suspend */ + if (cpufreq_suspended) + return 0; + if (policy->governor->max_transition_latency && policy->cpuinfo.transition_latency > policy->governor->max_transition_latency) { if (!gov) return -EINVAL; else { - printk(KERN_WARNING "%s governor failed, too long" - " transition latency of HW, fallback" - " to %s governor\n", - policy->governor->name, - gov->name); + pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n", + policy->governor->name, gov->name); policy->governor = gov; } } @@ -1883,7 +1906,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, return -EINVAL; pr_debug("__cpufreq_governor for CPU %u, event %u\n", - policy->cpu, event); + policy->cpu, event); mutex_lock(&cpufreq_governor_lock); if ((policy->governor_enabled && event == CPUFREQ_GOV_START) @@ -1950,9 +1973,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor) { -#ifdef CONFIG_HOTPLUG_CPU int cpu; -#endif if (!governor) return; @@ -1960,14 +1981,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor) if (cpufreq_disabled()) return; -#ifdef CONFIG_HOTPLUG_CPU for_each_present_cpu(cpu) { if (cpu_online(cpu)) continue; if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name)) strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0"); } -#endif mutex_lock(&cpufreq_governor_mutex); list_del(&governor->governor_list); @@ -2012,22 +2031,21 @@ EXPORT_SYMBOL(cpufreq_get_policy); static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy) { - int ret = 0, failed = 1; + struct cpufreq_governor *old_gov; + int ret; - pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, - new_policy->min, new_policy->max); + pr_debug("setting new policy for CPU %u: %u - %u kHz\n", + new_policy->cpu, new_policy->min, new_policy->max); memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); - if (new_policy->min > policy->max || new_policy->max < policy->min) { - ret = -EINVAL; - goto error_out; - } + if (new_policy->min > policy->max || new_policy->max < policy->min) + return -EINVAL; /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(new_policy); if (ret) - goto error_out; + return ret; /* adjust if necessary - all reasons */ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, @@ -2043,7 +2061,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, */ ret = cpufreq_driver->verify(new_policy); if (ret) - goto error_out; + return ret; /* notification of the new policy */ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, @@ -2053,63 +2071,53 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, policy->max = new_policy->max; pr_debug("new min and max freqs are %u - %u kHz\n", - policy->min, policy->max); + policy->min, policy->max); if (cpufreq_driver->setpolicy) { policy->policy = new_policy->policy; pr_debug("setting range\n"); - ret = cpufreq_driver->setpolicy(new_policy); - } else { - if (new_policy->governor != policy->governor) { - /* save old, working values */ - struct cpufreq_governor *old_gov = policy->governor; - - pr_debug("governor switch\n"); - - /* end old governor */ - if (policy->governor) { - __cpufreq_governor(policy, CPUFREQ_GOV_STOP); - up_write(&policy->rwsem); - __cpufreq_governor(policy, - CPUFREQ_GOV_POLICY_EXIT); - down_write(&policy->rwsem); - } + return cpufreq_driver->setpolicy(new_policy); + } - /* start new governor */ - policy->governor = new_policy->governor; - if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { - if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) { - failed = 0; - } else { - up_write(&policy->rwsem); - __cpufreq_governor(policy, - CPUFREQ_GOV_POLICY_EXIT); - down_write(&policy->rwsem); - } - } + if (new_policy->governor == policy->governor) + goto out; - if (failed) { - /* new governor failed, so re-start old one */ - pr_debug("starting governor %s failed\n", - policy->governor->name); - if (old_gov) { - policy->governor = old_gov; - __cpufreq_governor(policy, - CPUFREQ_GOV_POLICY_INIT); - __cpufreq_governor(policy, - CPUFREQ_GOV_START); - } - ret = -EINVAL; - goto error_out; - } - /* might be a policy change, too, so fall through */ - } - pr_debug("governor: change or update limits\n"); - ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + pr_debug("governor switch\n"); + + /* save old, working values */ + old_gov = policy->governor; + /* end old governor */ + if (old_gov) { + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + up_write(&policy->rwsem); + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + down_write(&policy->rwsem); } -error_out: - return ret; + /* start new governor */ + policy->governor = new_policy->governor; + if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { + if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) + goto out; + + up_write(&policy->rwsem); + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + down_write(&policy->rwsem); + } + + /* new governor failed, so re-start old one */ + pr_debug("starting governor %s failed\n", policy->governor->name); + if (old_gov) { + policy->governor = old_gov; + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); + __cpufreq_governor(policy, CPUFREQ_GOV_START); + } + + return -EINVAL; + + out: + pr_debug("governor: change or update limits\n"); + return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } /** @@ -2145,8 +2153,13 @@ int cpufreq_update_policy(unsigned int cpu) */ if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { new_policy.cur = cpufreq_driver->get(cpu); + if (WARN_ON(!new_policy.cur)) { + ret = -EIO; + goto no_policy; + } + if (!policy->cur) { - pr_debug("Driver did not initialize current freq"); + pr_debug("Driver did not initialize current freq\n"); policy->cur = new_policy.cur; } else { if (policy->cur != new_policy.cur && has_target()) @@ -2170,30 +2183,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, { unsigned int cpu = (unsigned long)hcpu; struct device *dev; - bool frozen = false; dev = get_cpu_device(cpu); if (dev) { - - if (action & CPU_TASKS_FROZEN) - frozen = true; - switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: - __cpufreq_add_dev(dev, NULL, frozen); - cpufreq_update_policy(cpu); + __cpufreq_add_dev(dev, NULL); break; case CPU_DOWN_PREPARE: - __cpufreq_remove_dev_prepare(dev, NULL, frozen); + __cpufreq_remove_dev_prepare(dev, NULL); break; case CPU_POST_DEAD: - __cpufreq_remove_dev_finish(dev, NULL, frozen); + __cpufreq_remove_dev_finish(dev, NULL); break; case CPU_DOWN_FAILED: - __cpufreq_add_dev(dev, NULL, frozen); + __cpufreq_add_dev(dev, NULL); break; } } @@ -2249,8 +2256,8 @@ int cpufreq_boost_trigger_state(int state) cpufreq_driver->boost_enabled = !state; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - pr_err("%s: Cannot %s BOOST\n", __func__, - state ? "enable" : "disable"); + pr_err("%s: Cannot %s BOOST\n", + __func__, state ? "enable" : "disable"); } return ret; @@ -2295,7 +2302,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) if (!driver_data || !driver_data->verify || !driver_data->init || !(driver_data->setpolicy || driver_data->target_index || - driver_data->target)) + driver_data->target) || + (driver_data->setpolicy && (driver_data->target_index || + driver_data->target))) return -EINVAL; pr_debug("trying to register driver %s\n", driver_data->name); @@ -2322,7 +2331,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ret = cpufreq_sysfs_create_file(&boost.attr); if (ret) { pr_err("%s: cannot register global BOOST sysfs file\n", - __func__); + __func__); goto err_null_driver; } } @@ -2345,7 +2354,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) /* if all ->init() calls failed, unregister */ if (ret) { pr_debug("no CPU initialized for driver %s\n", - driver_data->name); + driver_data->name); goto err_if_unreg; } } @@ -2409,7 +2418,6 @@ static int __init cpufreq_core_init(void) cpufreq_global_kobject = kobject_create(); BUG_ON(!cpufreq_global_kobject); - register_syscore_ops(&cpufreq_syscore_ops); return 0; } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 79911a27a48a..ecaaebf969fc 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu) cpufreq_cpu_put(policy); } -static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table) +static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) { unsigned int i, j, count = 0, ret = 0; struct cpufreq_stats *stat; - struct cpufreq_policy *current_policy; unsigned int alloc_size; unsigned int cpu = policy->cpu; + struct cpufreq_frequency_table *table; + + table = cpufreq_frequency_get_table(cpu); + if (unlikely(!table)) + return 0; + if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; stat = kzalloc(sizeof(*stat), GFP_KERNEL); if ((stat) == NULL) return -ENOMEM; - current_policy = cpufreq_cpu_get(cpu); - if (current_policy == NULL) { - ret = -EINVAL; - goto error_get_fail; - } - - ret = sysfs_create_group(¤t_policy->kobj, &stats_attr_group); + ret = sysfs_create_group(&policy->kobj, &stats_attr_group); if (ret) goto error_out; @@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stat->time_in_state) { ret = -ENOMEM; - goto error_out; + goto error_alloc; } stat->freq_table = (unsigned int *)(stat->time_in_state + count); @@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, stat->last_time = get_jiffies_64(); stat->last_index = freq_table_get_index(stat, policy->cur); spin_unlock(&cpufreq_stats_lock); - cpufreq_cpu_put(current_policy); return 0; +error_alloc: + sysfs_remove_group(&policy->kobj, &stats_attr_group); error_out: - cpufreq_cpu_put(current_policy); -error_get_fail: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; @@ -256,7 +253,6 @@ error_get_fail: static void cpufreq_stats_create_table(unsigned int cpu) { struct cpufreq_policy *policy; - struct cpufreq_frequency_table *table; /* * "likely(!policy)" because normally cpufreq_stats will be registered @@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu) if (likely(!policy)) return; - table = cpufreq_frequency_get_table(policy->cpu); - if (likely(table)) - __cpufreq_stats_create_table(policy, table); + __cpufreq_stats_create_table(policy); cpufreq_cpu_put(policy); } @@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, { int ret = 0; struct cpufreq_policy *policy = data; - struct cpufreq_frequency_table *table; - unsigned int cpu = policy->cpu; if (val == CPUFREQ_UPDATE_POLICY_CPU) { cpufreq_stats_update_policy_cpu(policy); return 0; } - table = cpufreq_frequency_get_table(cpu); - if (!table) - return 0; - if (val == CPUFREQ_CREATE_POLICY) - ret = __cpufreq_stats_create_table(policy, table); + ret = __cpufreq_stats_create_table(policy); else if (val == CPUFREQ_REMOVE_POLICY) __cpufreq_stats_free_table(policy); diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index 86559040c54c..d4573032cbbc 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = cris_freq_target, .init = cris_freq_cpu_init, - .exit = cpufreq_generic_exit, .name = "cris_freq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index 26d940d40b1d..13c3361437f7 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = cris_freq_target, .init = cris_freq_cpu_init, - .exit = cpufreq_generic_exit, .name = "cris_freq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index 2cf33848d86e..28a16dc6e02e 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = { .target_index = davinci_target, .get = cpufreq_generic_get, .init = davinci_cpu_init, - .exit = cpufreq_generic_exit, .name = "davinci", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 9012b8bb6b64..a0d2a423cea9 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy) unsigned int cpu = policy->cpu; /* Bye */ - cpufreq_frequency_table_put_attr(policy->cpu); kfree(eps_cpu[cpu]); eps_cpu[cpu] = NULL; return 0; diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index de08acff5101..c987e94708f5 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = elanfreq_target, .init = elanfreq_cpu_init, - .exit = cpufreq_generic_exit, .name = "elanfreq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index fcd2914d081a..f99cfe24e7bc 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -16,7 +16,6 @@ #include <linux/slab.h> #include <linux/regulator/consumer.h> #include <linux/cpufreq.h> -#include <linux/suspend.h> #include <linux/platform_device.h> #include <plat/cpu.h> @@ -24,12 +23,8 @@ #include "exynos-cpufreq.h" static struct exynos_dvfs_info *exynos_info; - static struct regulator *arm_regulator; - static unsigned int locking_frequency; -static bool frequency_locked; -static DEFINE_MUTEX(cpufreq_lock); static int exynos_cpufreq_get_index(unsigned int freq) { @@ -134,83 +129,13 @@ out: static int exynos_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; - int ret = 0; - - mutex_lock(&cpufreq_lock); - - if (frequency_locked) - goto out; - - ret = exynos_cpufreq_scale(freq_table[index].frequency); - -out: - mutex_unlock(&cpufreq_lock); - - return ret; -} - -#ifdef CONFIG_PM -static int exynos_cpufreq_suspend(struct cpufreq_policy *policy) -{ - return 0; -} - -static int exynos_cpufreq_resume(struct cpufreq_policy *policy) -{ - return 0; -} -#endif - -/** - * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume - * context - * @notifier - * @pm_event - * @v - * - * While frequency_locked == true, target() ignores every frequency but - * locking_frequency. The locking_frequency value is the initial frequency, - * which is set by the bootloader. In order to eliminate possible - * inconsistency in clock values, we save and restore frequencies during - * suspend and resume and block CPUFREQ activities. Note that the standard - * suspend/resume cannot be used as they are too deep (syscore_ops) for - * regulator actions. - */ -static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier, - unsigned long pm_event, void *v) -{ - int ret; - - switch (pm_event) { - case PM_SUSPEND_PREPARE: - mutex_lock(&cpufreq_lock); - frequency_locked = true; - mutex_unlock(&cpufreq_lock); - - ret = exynos_cpufreq_scale(locking_frequency); - if (ret < 0) - return NOTIFY_BAD; - - break; - - case PM_POST_SUSPEND: - mutex_lock(&cpufreq_lock); - frequency_locked = false; - mutex_unlock(&cpufreq_lock); - break; - } - - return NOTIFY_OK; + return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency); } -static struct notifier_block exynos_cpufreq_nb = { - .notifier_call = exynos_cpufreq_pm_notifier, -}; - static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { policy->clk = exynos_info->cpu_clk; + policy->suspend_freq = locking_frequency; return cpufreq_generic_init(policy, exynos_info->freq_table, 100000); } @@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = { .target_index = exynos_target, .get = cpufreq_generic_get, .init = exynos_cpufreq_cpu_init, - .exit = cpufreq_generic_exit, .name = "exynos_cpufreq", .attr = cpufreq_generic_attr, #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW .boost_supported = true, #endif #ifdef CONFIG_PM - .suspend = exynos_cpufreq_suspend, - .resume = exynos_cpufreq_resume, + .suspend = cpufreq_generic_suspend, #endif }; @@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) goto err_vdd_arm; } + /* Done here as we want to capture boot frequency */ locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000; - register_pm_notifier(&exynos_cpufreq_nb); - - if (cpufreq_register_driver(&exynos_driver)) { - pr_err("%s: failed to register cpufreq driver\n", __func__); - goto err_cpufreq; - } - - return 0; -err_cpufreq: - unregister_pm_notifier(&exynos_cpufreq_nb); + if (!cpufreq_register_driver(&exynos_driver)) + return 0; + pr_err("%s: failed to register cpufreq driver\n", __func__); regulator_put(arm_regulator); err_vdd_arm: kfree(exynos_info); diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 49b756015316..7f776aa91e2f 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = { .target_index = exynos_target, .get = cpufreq_generic_get, .init = exynos_cpufreq_cpu_init, - .exit = cpufreq_generic_exit, .name = CPUFREQ_NAME, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 8e54f97899ba..65a477075b3f 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); /* - * Generic routine to verify policy & frequency table, requires driver to call - * cpufreq_frequency_table_get_attr() prior to it. + * Generic routine to verify policy & frequency table, requires driver to set + * policy->freq_table prior to it. */ int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) { @@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); -static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); - /** * show_available_freqs - show available frequencies for the specified CPU */ @@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, bool show_boost) { unsigned int i = 0; - unsigned int cpu = policy->cpu; ssize_t count = 0; - struct cpufreq_frequency_table *table; + struct cpufreq_frequency_table *table = policy->freq_table; - if (!per_cpu(cpufreq_show_table, cpu)) + if (!table) return -ENODEV; - table = per_cpu(cpufreq_show_table, cpu); - for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { if (table[i].frequency == CPUFREQ_ENTRY_INVALID) continue; @@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = { }; EXPORT_SYMBOL_GPL(cpufreq_generic_attr); -/* - * if you use these, you must assure that the frequency table is valid - * all the time between get_attr and put_attr! - */ -void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, - unsigned int cpu) -{ - pr_debug("setting show_table for cpu %u to %p\n", cpu, table); - per_cpu(cpufreq_show_table, cpu) = table; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); - -void cpufreq_frequency_table_put_attr(unsigned int cpu) -{ - pr_debug("clearing show_table for cpu %u\n", cpu); - per_cpu(cpufreq_show_table, cpu) = NULL; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); - int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table) { int ret = cpufreq_frequency_table_cpuinfo(policy, table); if (!ret) - cpufreq_frequency_table_get_attr(table, policy->cpu); + policy->freq_table = table; return ret; } EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); -void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy) -{ - pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n", - policy->cpu, policy->last_cpu); - per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table, - policy->last_cpu); - per_cpu(cpufreq_show_table, policy->last_cpu) = NULL; -} +struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu); struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) { - return per_cpu(cpufreq_show_table, cpu); + struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); + return policy ? policy->freq_table : NULL; } EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 53c6ac637e10..a22b5d182e0e 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit ( pr_debug("acpi_cpufreq_cpu_exit\n"); if (data) { - cpufreq_frequency_table_put_attr(policy->cpu); acpi_io_data[policy->cpu] = NULL; acpi_processor_unregister_performance(&data->acpi_data, policy->cpu); diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index ce69059be1fc..e27fca86fe4f 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { .target_index = imx6q_set_target, .get = cpufreq_generic_get, .init = imx6q_cpufreq_init, - .exit = cpufreq_generic_exit, .name = "imx6q-cpufreq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 2cd36b9297f3..bcb9a6d0ae11 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -99,8 +99,7 @@ struct cpudata { u64 prev_aperf; u64 prev_mperf; unsigned long long prev_tsc; - int sample_ptr; - struct sample samples[SAMPLE_COUNT]; + struct sample sample; }; static struct cpudata **all_cpu_data; @@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy, pid->setpoint = setpoint; pid->deadband = deadband; pid->integral = int_tofp(integral); - pid->last_err = setpoint - busy; + pid->last_err = int_tofp(setpoint) - int_tofp(busy); } static inline void pid_p_gain_set(struct _pid *pid, int percent) @@ -447,7 +446,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate) if (limits.no_turbo) val |= (u64)1 << 32; - wrmsrl(MSR_IA32_PERF_CTL, val); + wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); } static struct cpu_defaults core_params = { @@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu) mperf = mperf >> FRAC_BITS; tsc = tsc >> FRAC_BITS; - cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; - cpu->samples[cpu->sample_ptr].aperf = aperf; - cpu->samples[cpu->sample_ptr].mperf = mperf; - cpu->samples[cpu->sample_ptr].tsc = tsc; - cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; - cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; - cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc; + cpu->sample.aperf = aperf; + cpu->sample.mperf = mperf; + cpu->sample.tsc = tsc; + cpu->sample.aperf -= cpu->prev_aperf; + cpu->sample.mperf -= cpu->prev_mperf; + cpu->sample.tsc -= cpu->prev_tsc; - intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); + intel_pstate_calc_busy(cpu, &cpu->sample); cpu->prev_aperf = aperf; cpu->prev_mperf = mperf; @@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) { int32_t core_busy, max_pstate, current_pstate; - core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; + core_busy = cpu->sample.core_pct_busy; max_pstate = int_tofp(cpu->pstate.max_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate); core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); @@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data) intel_pstate_sample(cpu); - sample = &cpu->samples[cpu->sample_ptr]; + sample = &cpu->sample; intel_pstate_adjust_busy_pstate(cpu); @@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) cpu = all_cpu_data[cpu_num]; if (!cpu) return 0; - sample = &cpu->samples[cpu->sample_ptr]; + sample = &cpu->sample; return sample->freq; } @@ -773,14 +771,17 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy) return 0; } -static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) +static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) { - int cpu = policy->cpu; + int cpu_num = policy->cpu; + struct cpudata *cpu = all_cpu_data[cpu_num]; - del_timer(&all_cpu_data[cpu]->timer); - kfree(all_cpu_data[cpu]); - all_cpu_data[cpu] = NULL; - return 0; + pr_info("intel_pstate CPU %d exiting\n", cpu_num); + + del_timer(&all_cpu_data[cpu_num]->timer); + intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); + kfree(all_cpu_data[cpu_num]); + all_cpu_data[cpu_num] = NULL; } static int intel_pstate_cpu_init(struct cpufreq_policy *policy) @@ -818,7 +819,7 @@ static struct cpufreq_driver intel_pstate_driver = { .setpolicy = intel_pstate_set_policy, .get = intel_pstate_get, .init = intel_pstate_cpu_init, - .exit = intel_pstate_cpu_exit, + .stop_cpu = intel_pstate_stop_cpu, .name = "intel_pstate", }; diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index eb7abe345b50..3d114bc5a97a 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = kirkwood_cpufreq_target, .init = kirkwood_cpufreq_cpu_init, - .exit = cpufreq_generic_exit, .name = "kirkwood-cpufreq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 45bafddfd8ea..7b94da3d2d10 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = { .target_index = longhaul_target, .get = longhaul_get, .init = longhaul_cpu_init, - .exit = cpufreq_generic_exit, .name = "longhaul", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index b6581abc9207..a3588d61d933 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); clk_put(policy->clk); return 0; } diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 590f5b66d181..5f69c9aa703c 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -143,7 +143,6 @@ fail: static int omap_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); freq_table_free(); clk_put(policy->clk); return 0; diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 3d1cba9fd5f9..74f593e70e19 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, - .exit = cpufreq_generic_exit, .get = cpufreq_p4_get, .name = "p4-clockmod", .attr = cpufreq_generic_attr, diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 0426008380d8..6a2b7d3e85a7 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) if (sdcpwr_mapbase) iounmap(sdcpwr_mapbase); - cpufreq_frequency_table_put_attr(policy->cpu); return 0; } diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index b9a444e358b5..ce27e6c26c94 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) if (i == max_multiplier) powernow_k6_target(policy, i); } - cpufreq_frequency_table_put_attr(policy->cpu); return 0; } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 946708a1d745..0e68e0275621 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) static int powernow_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); - #ifdef CONFIG_X86_POWERNOW_K7_ACPI if (acpi_processor_perf) { acpi_processor_unregister_performance(acpi_processor_perf, 0); diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 6684e0342792..27eb2be44de5 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) powernow_k8_cpu_exit_acpi(data); - cpufreq_frequency_table_put_attr(pol->cpu); - kfree(data->powernow_table); kfree(data); for_each_cpu(cpu, pol->cpus) diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index 051000f44ca2..3bd9123e7026 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -21,6 +21,7 @@ #include <linux/of.h> #include <linux/slab.h> #include <linux/smp.h> +#include <sysdev/fsl_soc.h> /** * struct cpu_data - per CPU data struct @@ -205,7 +206,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) for_each_cpu(i, per_cpu(cpu_mask, cpu)) per_cpu(cpu_data, i) = data; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cpuinfo.transition_latency = + (12 * NSEC_PER_SEC) / fsl_get_sys_freq(); of_node_put(np); return 0; @@ -228,7 +230,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) struct cpu_data *data = per_cpu(cpu_data, policy->cpu); unsigned int cpu; - cpufreq_frequency_table_put_attr(policy->cpu); of_node_put(data->parent); kfree(data->table); kfree(data); diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index e42ca9c31cea..af7b1cabd1e7 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = cbe_cpufreq_target, .init = cbe_cpufreq_cpu_init, - .exit = cpufreq_generic_exit, .name = "cbe-cpufreq", .flags = CPUFREQ_CONST_LOOPS, }; diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index a9195a86b069..e24269ab4e9b 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = pxa_set_target, .init = pxa_cpufreq_init, - .exit = cpufreq_generic_exit, .get = pxa_cpufreq_get, .name = "PXA2xx", }; diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index 3785687e9d70..a01275900389 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = pxa3xx_cpufreq_set, .init = pxa3xx_cpufreq_init, - .exit = cpufreq_generic_exit, .get = pxa3xx_cpufreq_get, .name = "pxa3xx-cpufreq", }; diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 55a8e9fa9435..72421534fff5 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -18,7 +18,6 @@ #include <linux/cpufreq.h> #include <linux/reboot.h> #include <linux/regulator/consumer.h> -#include <linux/suspend.h> #include <mach/map.h> #include <mach/regs-clock.h> @@ -435,18 +434,6 @@ exit: return ret; } -#ifdef CONFIG_PM -static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy) -{ - return 0; -} - -static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy) -{ - return 0; -} -#endif - static int check_mem_type(void __iomem *dmc_reg) { unsigned long val; @@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); + policy->suspend_freq = SLEEP_FREQ; return cpufreq_generic_init(policy, s5pv210_freq_table, 40000); out_dmc1: @@ -511,32 +499,6 @@ out_dmc0: return ret; } -static int s5pv210_cpufreq_notifier_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - int ret; - - switch (event) { - case PM_SUSPEND_PREPARE: - ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0); - if (ret < 0) - return NOTIFY_BAD; - - /* Disable updation of cpu frequency */ - no_cpufreq_access = true; - return NOTIFY_OK; - case PM_POST_RESTORE: - case PM_POST_SUSPEND: - /* Enable updation of cpu frequency */ - no_cpufreq_access = false; - cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0); - - return NOTIFY_OK; - } - - return NOTIFY_DONE; -} - static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = { .init = s5pv210_cpu_init, .name = "s5pv210", #ifdef CONFIG_PM - .suspend = s5pv210_cpufreq_suspend, - .resume = s5pv210_cpufreq_resume, + .suspend = cpufreq_generic_suspend, + .resume = cpufreq_generic_suspend, /* We need to set SLEEP FREQ again */ #endif }; -static struct notifier_block s5pv210_cpufreq_notifier = { - .notifier_call = s5pv210_cpufreq_notifier_event, -}; - static struct notifier_block s5pv210_cpufreq_reboot_notifier = { .notifier_call = s5pv210_cpufreq_reboot_notifier_event, }; @@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void) return PTR_ERR(int_regulator); } - register_pm_notifier(&s5pv210_cpufreq_notifier); register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); return cpufreq_register_driver(&s5pv210_driver); diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 6adb354e359c..69371bf0886d 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = sc520_freq_target, .init = sc520_freq_cpu_init, - .exit = cpufreq_generic_exit, .name = "sc520_freq", .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index 387af12503a6..696170ebd3a3 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) unsigned int cpu = policy->cpu; struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); - cpufreq_frequency_table_put_attr(cpu); clk_put(cpuclk); return 0; diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 62aa23e219d4..b73feeb666f9 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us2e_driver) { - cpufreq_frequency_table_put_attr(policy->cpu); + if (cpufreq_us2e_driver) us2e_freq_target(policy, 0); - } return 0; } diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 724ffbd7105d..9bb42ba50efa 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) static int us3_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us3_driver) { - cpufreq_frequency_table_put_attr(policy->cpu); + if (cpufreq_us3_driver) us3_freq_target(policy, 0); - } return 0; } diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 5c86e3fa5593..4cfdcff8a310 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> @@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = { .target_index = spear_cpufreq_target, .get = cpufreq_generic_get, .init = spear_cpufreq_init, - .exit = cpufreq_generic_exit, .attr = cpufreq_generic_attr, }; -static int spear_cpufreq_driver_init(void) +static int spear_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; const struct property *prop; @@ -235,7 +235,15 @@ out_put_node: of_node_put(np); return ret; } -late_initcall(spear_cpufreq_driver_init); + +static struct platform_driver spear_cpufreq_platdrv = { + .driver = { + .name = "spear-cpufreq", + .owner = THIS_MODULE, + }, + .probe = spear_cpufreq_probe, +}; +module_platform_driver(spear_cpufreq_platdrv); MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>"); MODULE_DESCRIPTION("SPEAr CPUFreq driver"); diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 4e1daca5ce3b..6723f0390f20 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) if (!per_cpu(centrino_model, cpu)) return -ENODEV; - cpufreq_frequency_table_put_attr(cpu); - per_cpu(centrino_model, cpu) = NULL; return 0; diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 7639b2be2a90..394ac159312a 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = speedstep_target, .init = speedstep_cpu_init, - .exit = cpufreq_generic_exit, .get = speedstep_get, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index 998c17b42200..db5d274dc13a 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = speedstep_target, .init = speedstep_cpu_init, - .exit = cpufreq_generic_exit, .get = speedstep_get, .resume = speedstep_resume, .attr = cpufreq_generic_attr, diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index e652c1bd8d0f..63f00598a251 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -26,7 +26,6 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/suspend.h> static struct cpufreq_frequency_table freq_table[] = { { .frequency = 216000 }, @@ -47,9 +46,6 @@ static struct clk *pll_x_clk; static struct clk *pll_p_clk; static struct clk *emc_clk; -static DEFINE_MUTEX(tegra_cpu_lock); -static bool is_suspended; - static int tegra_cpu_clk_set_rate(unsigned long rate) { int ret; @@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy, static int tegra_target(struct cpufreq_policy *policy, unsigned int index) { - int ret = -EBUSY; - - mutex_lock(&tegra_cpu_lock); - - if (!is_suspended) - ret = tegra_update_cpu_speed(policy, - freq_table[index].frequency); - - mutex_unlock(&tegra_cpu_lock); - return ret; + return tegra_update_cpu_speed(policy, freq_table[index].frequency); } -static int tegra_pm_notify(struct notifier_block *nb, unsigned long event, - void *dummy) -{ - mutex_lock(&tegra_cpu_lock); - if (event == PM_SUSPEND_PREPARE) { - struct cpufreq_policy *policy = cpufreq_cpu_get(0); - is_suspended = true; - pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n", - freq_table[0].frequency); - if (clk_get_rate(cpu_clk) / 1000 != freq_table[0].frequency) - tegra_update_cpu_speed(policy, freq_table[0].frequency); - cpufreq_cpu_put(policy); - } else if (event == PM_POST_SUSPEND) { - is_suspended = false; - } - mutex_unlock(&tegra_cpu_lock); - - return NOTIFY_OK; -} - -static struct notifier_block tegra_cpu_pm_notifier = { - .notifier_call = tegra_pm_notify, -}; - static int tegra_cpu_init(struct cpufreq_policy *policy) { int ret; @@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) return ret; } - if (policy->cpu == 0) - register_pm_notifier(&tegra_cpu_pm_notifier); - policy->clk = cpu_clk; + policy->suspend_freq = freq_table[0].frequency; return 0; } static int tegra_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); clk_disable_unprepare(cpu_clk); clk_disable_unprepare(emc_clk); return 0; @@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = { .exit = tegra_cpu_exit, .name = "tegra", .attr = cpufreq_generic_attr, +#ifdef CONFIG_PM + .suspend = cpufreq_generic_suspend, +#endif }; static int __init tegra_cpufreq_init(void) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 09d05ab262be..cb20fd915be8 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -85,7 +85,8 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, time_end = ktime_get(); - local_irq_enable(); + if (!cpuidle_state_is_coupled(dev, drv, entered_state)) + local_irq_enable(); diff = ktime_to_us(ktime_sub(time_end, time_start)); if (diff > INT_MAX) diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 06dbe7c86199..136d6a283e0a 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -209,7 +209,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->exit_latency = 0; state->target_residency = 0; state->power_usage = -1; - state->flags = 0; + state->flags = CPUIDLE_FLAG_TIME_VALID; state->enter = poll_idle; state->disabled = false; } diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index cf7f2f0e4ef5..71b523293354 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -122,9 +122,8 @@ struct menu_device { int last_state_idx; int needs_update; - unsigned int expected_us; + unsigned int next_timer_us; unsigned int predicted_us; - unsigned int exit_us; unsigned int bucket; unsigned int correction_factor[BUCKETS]; unsigned int intervals[INTERVALS]; @@ -257,7 +256,7 @@ again: stddev = int_sqrt(stddev); if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) || stddev <= 20) { - if (data->expected_us > avg) + if (data->next_timer_us > avg) data->predicted_us = avg; return; } @@ -289,7 +288,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); int i; - int multiplier; + unsigned int interactivity_req; struct timespec t; if (data->needs_update) { @@ -298,7 +297,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) } data->last_state_idx = 0; - data->exit_us = 0; /* Special case when user has set very strict latency requirement */ if (unlikely(latency_req == 0)) @@ -306,13 +304,11 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) /* determine the expected residency time, round up */ t = ktime_to_timespec(tick_nohz_get_sleep_length()); - data->expected_us = + data->next_timer_us = t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC; - data->bucket = which_bucket(data->expected_us); - - multiplier = performance_multiplier(); + data->bucket = which_bucket(data->next_timer_us); /* * if the correction factor is 0 (eg first time init or cpu hotplug @@ -326,17 +322,26 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * operands are 32 bits. * Make sure to round up for half microseconds. */ - data->predicted_us = div_round64((uint64_t)data->expected_us * + data->predicted_us = div_round64((uint64_t)data->next_timer_us * data->correction_factor[data->bucket], RESOLUTION * DECAY); get_typical_interval(data); /* + * Performance multiplier defines a minimum predicted idle + * duration / latency ratio. Adjust the latency limit if + * necessary. + */ + interactivity_req = data->predicted_us / performance_multiplier(); + if (latency_req > interactivity_req) + latency_req = interactivity_req; + + /* * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ - if (data->expected_us > 5 && + if (data->next_timer_us > 5 && !drv->states[CPUIDLE_DRIVER_STATE_START].disabled && dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; @@ -355,11 +360,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) continue; if (s->exit_latency > latency_req) continue; - if (s->exit_latency * multiplier > data->predicted_us) - continue; data->last_state_idx = i; - data->exit_us = s->exit_latency; } return data->last_state_idx; @@ -390,36 +392,47 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int last_idx = data->last_state_idx; - unsigned int last_idle_us = cpuidle_get_last_residency(dev); struct cpuidle_state *target = &drv->states[last_idx]; unsigned int measured_us; unsigned int new_factor; /* - * Ugh, this idle state doesn't support residency measurements, so we - * are basically lost in the dark. As a compromise, assume we slept - * for the whole expected time. + * Try to figure out how much time passed between entry to low + * power state and occurrence of the wakeup event. + * + * If the entered idle state didn't support residency measurements, + * we are basically lost in the dark how much time passed. + * As a compromise, assume we slept for the whole expected time. + * + * Any measured amount of time will include the exit latency. + * Since we are interested in when the wakeup begun, not when it + * was completed, we must substract the exit latency. However, if + * the measured amount of time is less than the exit latency, + * assume the state was never reached and the exit latency is 0. */ - if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID))) - last_idle_us = data->expected_us; + if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID))) { + /* Use timer value as is */ + measured_us = data->next_timer_us; + } else { + /* Use measured value */ + measured_us = cpuidle_get_last_residency(dev); - measured_us = last_idle_us; - - /* - * We correct for the exit latency; we are assuming here that the - * exit latency happens after the event that we're interested in. - */ - if (measured_us > data->exit_us) - measured_us -= data->exit_us; + /* Deduct exit latency */ + if (measured_us > target->exit_latency) + measured_us -= target->exit_latency; + /* Make sure our coefficients do not exceed unity */ + if (measured_us > data->next_timer_us) + measured_us = data->next_timer_us; + } /* Update our correction ratio */ new_factor = data->correction_factor[data->bucket]; new_factor -= new_factor / DECAY; - if (data->expected_us > 0 && measured_us < MAX_INTERESTING) - new_factor += RESOLUTION * measured_us / data->expected_us; + if (data->next_timer_us > 0 && measured_us < MAX_INTERESTING) + new_factor += RESOLUTION * measured_us / data->next_timer_us; else /* * we were idle so long that we count it as a perfect @@ -439,7 +452,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) data->correction_factor[data->bucket] = new_factor; /* update the repeating-pattern data */ - data->intervals[data->interval_ptr++] = last_idle_us; + data->intervals[data->interval_ptr++] = measured_us; if (data->interval_ptr >= INTERVALS) data->interval_ptr = 0; } diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index a0b2f7e0eedb..2042ec3656ba 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -91,26 +91,35 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) */ static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) { - int lev, prev_lev; + int lev, prev_lev, ret = 0; unsigned long cur_time; - lev = devfreq_get_freq_level(devfreq, freq); - if (lev < 0) - return lev; - cur_time = jiffies; - devfreq->time_in_state[lev] += + + prev_lev = devfreq_get_freq_level(devfreq, devfreq->previous_freq); + if (prev_lev < 0) { + ret = prev_lev; + goto out; + } + + devfreq->time_in_state[prev_lev] += cur_time - devfreq->last_stat_updated; - if (freq != devfreq->previous_freq) { - prev_lev = devfreq_get_freq_level(devfreq, - devfreq->previous_freq); + + lev = devfreq_get_freq_level(devfreq, freq); + if (lev < 0) { + ret = lev; + goto out; + } + + if (lev != prev_lev) { devfreq->trans_table[(prev_lev * devfreq->profile->max_state) + lev]++; devfreq->total_trans++; } - devfreq->last_stat_updated = cur_time; - return 0; +out: + devfreq->last_stat_updated = cur_time; + return ret; } /** diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig index 508cf99a292d..17f928ec84ea 100644 --- a/drivers/gpu/drm/gma500/Kconfig +++ b/drivers/gpu/drm/gma500/Kconfig @@ -10,7 +10,6 @@ config DRM_GMA500 # GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915 select ACPI_VIDEO if ACPI select BACKLIGHT_CLASS_DEVICE if ACPI - select VIDEO_OUTPUT_CONTROL if ACPI select INPUT if ACPI help Say yes for an experimental 2D KMS framebuffer driver for the diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 73ed59eff139..bea2d67196fb 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -14,7 +14,6 @@ config DRM_I915 # but for select to work, need to select ACPI_VIDEO's dependencies, ick select BACKLIGHT_LCD_SUPPORT if ACPI select BACKLIGHT_CLASS_DEVICE if ACPI - select VIDEO_OUTPUT_CONTROL if ACPI select INPUT if ACPI select ACPI_VIDEO if ACPI select ACPI_BUTTON if ACPI diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 7cf787d697b1..637c29a33127 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -11,7 +11,7 @@ config DRM_NOUVEAU select FB select FRAMEBUFFER_CONSOLE if !EXPERT select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT - select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT + select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT select X86_PLATFORM_DEVICES if ACPI && X86 select ACPI_WMI if ACPI && X86 select MXM_WMI if ACPI && X86 @@ -19,7 +19,6 @@ config DRM_NOUVEAU # Similar to i915, we need to select ACPI_VIDEO and it's dependencies select BACKLIGHT_LCD_SUPPORT if ACPI && X86 select BACKLIGHT_CLASS_DEVICE if ACPI && X86 - select VIDEO_OUTPUT_CONTROL if ACPI && X86 select INPUT if ACPI && X86 select THERMAL if ACPI && X86 select ACPI_VIDEO if ACPI && X86 diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 5c342b3139e8..3c0f57efe7b1 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -134,7 +134,8 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) } else if (!ts->low_latency_req.dev) { /* First contact, request 100 us latency. */ dev_pm_qos_add_ancestor_request(&ts->client->dev, - &ts->low_latency_req, 100); + &ts->low_latency_req, + DEV_PM_QOS_RESUME_LATENCY, 100); } /* SYN_REPORT */ diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index d72783dd7b96..c0670237e7a2 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -897,7 +897,7 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) if (!flctl->qos_request) { ret = dev_pm_qos_add_request(&flctl->pdev->dev, &flctl->pm_qos, - DEV_PM_QOS_LATENCY, + DEV_PM_QOS_RESUME_LATENCY, 100); if (ret < 0) dev_err(&flctl->pdev->dev, diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b6162be4df40..2b859249303b 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -93,7 +93,6 @@ struct acpiphp_slot { struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ struct slot *slot; - struct mutex crit_sect; u8 device; /* pci device# */ u32 flags; /* see below */ @@ -117,20 +116,30 @@ struct acpiphp_func { }; struct acpiphp_context { - acpi_handle handle; + struct acpi_hotplug_context hp; struct acpiphp_func func; struct acpiphp_bridge *bridge; unsigned int refcount; }; +static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp) +{ + return container_of(hp, struct acpiphp_context, hp); +} + static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func) { return container_of(func, struct acpiphp_context, func); } +static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func) +{ + return func_to_context(func)->hp.self; +} + static inline acpi_handle func_to_handle(struct acpiphp_func *func) { - return func_to_context(func)->handle; + return func_to_acpi_device(func)->handle; } /* @@ -158,7 +167,6 @@ struct acpiphp_attention_info #define FUNC_HAS_STA (0x00000001) #define FUNC_HAS_EJ0 (0x00000002) -#define FUNC_HAS_DCK (0x00000004) /* function prototypes */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 7c7a388c85ab..828acf422c17 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -58,71 +58,59 @@ static LIST_HEAD(bridge_list); static DEFINE_MUTEX(bridge_mutex); -static DEFINE_MUTEX(acpiphp_context_lock); -static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); +static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type); +static void acpiphp_post_dock_fixup(struct acpi_device *adev); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); -static void hotplug_event(acpi_handle handle, u32 type, void *data); +static void hotplug_event(u32 type, struct acpiphp_context *context); static void free_bridge(struct kref *kref); -static void acpiphp_context_handler(acpi_handle handle, void *context) -{ - /* Intentionally empty. */ -} - /** * acpiphp_init_context - Create hotplug context and grab a reference to it. - * @handle: ACPI object handle to create the context for. + * @adev: ACPI device object to create the context for. * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock. */ -static struct acpiphp_context *acpiphp_init_context(acpi_handle handle) +static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) { struct acpiphp_context *context; - acpi_status status; context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) return NULL; - context->handle = handle; context->refcount = 1; - status = acpi_attach_data(handle, acpiphp_context_handler, context); - if (ACPI_FAILURE(status)) { - kfree(context); - return NULL; - } + acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL, + acpiphp_post_dock_fixup); return context; } /** * acpiphp_get_context - Get hotplug context and grab a reference to it. - * @handle: ACPI object handle to get the context for. + * @adev: ACPI device object to get the context for. * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock. */ -static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) +static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev) { - struct acpiphp_context *context = NULL; - acpi_status status; - void *data; + struct acpiphp_context *context; - status = acpi_get_data(handle, acpiphp_context_handler, &data); - if (ACPI_SUCCESS(status)) { - context = data; - context->refcount++; - } + if (!adev->hp) + return NULL; + + context = to_acpiphp_context(adev->hp); + context->refcount++; return context; } /** * acpiphp_put_context - Drop a reference to ACPI hotplug context. - * @handle: ACPI object handle to put the context for. + * @context: ACPI hotplug context to drop a reference to. * * The context object is removed if there are no more references to it. * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock. */ static void acpiphp_put_context(struct acpiphp_context *context) { @@ -130,7 +118,7 @@ static void acpiphp_put_context(struct acpiphp_context *context) return; WARN_ON(context->bridge); - acpi_detach_data(context->handle, acpiphp_context_handler); + context->hp.self->hp = NULL; kfree(context); } @@ -144,6 +132,27 @@ static inline void put_bridge(struct acpiphp_bridge *bridge) kref_put(&bridge->ref, free_bridge); } +static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev) +{ + struct acpiphp_context *context; + + acpi_lock_hp_context(); + context = acpiphp_get_context(adev); + if (!context || context->func.parent->is_going_away) { + acpi_unlock_hp_context(); + return NULL; + } + get_bridge(context->func.parent); + acpiphp_put_context(context); + acpi_unlock_hp_context(); + return context; +} + +static void acpiphp_let_context_go(struct acpiphp_context *context) +{ + put_bridge(context->func.parent); +} + static void free_bridge(struct kref *kref) { struct acpiphp_context *context; @@ -151,7 +160,7 @@ static void free_bridge(struct kref *kref) struct acpiphp_slot *slot, *next; struct acpiphp_func *func, *tmp; - mutex_lock(&acpiphp_context_lock); + acpi_lock_hp_context(); bridge = container_of(kref, struct acpiphp_bridge, ref); @@ -175,31 +184,32 @@ static void free_bridge(struct kref *kref) pci_dev_put(bridge->pci_dev); kfree(bridge); - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); } -/* - * the _DCK method can do funny things... and sometimes not - * hah-hah funny. +/** + * acpiphp_post_dock_fixup - Post-dock fixups for PCI devices. + * @adev: ACPI device object corresponding to a PCI device. * - * TBD - figure out a way to only call fixups for - * systems that require them. + * TBD - figure out a way to only call fixups for systems that require them. */ -static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) +static void acpiphp_post_dock_fixup(struct acpi_device *adev) { - struct acpiphp_context *context = data; - struct pci_bus *bus = context->func.slot->bus; + struct acpiphp_context *context = acpiphp_grab_context(adev); + struct pci_bus *bus; u32 buses; - if (!bus->self) + if (!context) return; + bus = context->func.slot->bus; + if (!bus->self) + goto out; + /* fixup bad _DCK function that rewrites * secondary bridge on slot */ - pci_read_config_dword(bus->self, - PCI_PRIMARY_BUS, - &buses); + pci_read_config_dword(bus->self, PCI_PRIMARY_BUS, &buses); if (((buses >> 8) & 0xff) != bus->busn_res.start) { buses = (buses & 0xff000000) @@ -208,33 +218,11 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | ((unsigned int)(bus->busn_res.end) << 16); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); } -} - -static void dock_event(acpi_handle handle, u32 type, void *data) -{ - struct acpiphp_context *context; - - mutex_lock(&acpiphp_context_lock); - context = acpiphp_get_context(handle); - if (!context || WARN_ON(context->handle != handle) - || context->func.parent->is_going_away) { - mutex_unlock(&acpiphp_context_lock); - return; - } - get_bridge(context->func.parent); - acpiphp_put_context(context); - mutex_unlock(&acpiphp_context_lock); - - hotplug_event(handle, type, data); - put_bridge(context->func.parent); + out: + acpiphp_let_context_go(context); } -static const struct acpi_dock_ops acpiphp_dock_ops = { - .fixup = post_dock_fixups, - .handler = dock_event, -}; - /* Check whether the PCI device is managed by native PCIe hotplug driver */ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) { @@ -264,26 +252,19 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) return true; } -static void acpiphp_dock_init(void *data) -{ - struct acpiphp_context *context = data; - - get_bridge(context->func.parent); -} - -static void acpiphp_dock_release(void *data) -{ - struct acpiphp_context *context = data; - - put_bridge(context->func.parent); -} - -/* callback routine to register each ACPI PCI slot object */ -static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, - void **rv) +/** + * acpiphp_add_context - Add ACPIPHP context to an ACPI device object. + * @handle: ACPI handle of the object to add a context to. + * @lvl: Not used. + * @data: The object's parent ACPIPHP bridge. + * @rv: Not used. + */ +static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, + void **rv) { struct acpiphp_bridge *bridge = data; struct acpiphp_context *context; + struct acpi_device *adev; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; acpi_status status = AE_OK; @@ -293,9 +274,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, struct pci_dev *pdev = bridge->pci_dev; u32 val; - if (pdev && device_is_managed_by_native_pciehp(pdev)) - return AE_OK; - status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) @@ -303,31 +281,34 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, "can't evaluate _ADR (%#x)\n", status); return AE_OK; } + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; device = (adr >> 16) & 0xffff; function = adr & 0xffff; - mutex_lock(&acpiphp_context_lock); - context = acpiphp_init_context(handle); + acpi_lock_hp_context(); + context = acpiphp_init_context(adev); if (!context) { - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); acpi_handle_err(handle, "No hotplug context\n"); return AE_NOT_EXIST; } newfunc = &context->func; newfunc->function = function; newfunc->parent = bridge; - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); - if (acpi_has_method(handle, "_EJ0")) + /* + * If this is a dock device, its _EJ0 should be executed by the dock + * notify handler after calling _DCK. + */ + if (!is_dock_device(adev) && acpi_has_method(handle, "_EJ0")) newfunc->flags = FUNC_HAS_EJ0; if (acpi_has_method(handle, "_STA")) newfunc->flags |= FUNC_HAS_STA; - if (acpi_has_method(handle, "_DCK")) - newfunc->flags |= FUNC_HAS_DCK; - /* search for objects that share the same slot */ list_for_each_entry(slot, &bridge->slots, node) if (slot->device == device) @@ -335,19 +316,26 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { - status = AE_NO_MEMORY; - goto err; + acpi_lock_hp_context(); + acpiphp_put_context(context); + acpi_unlock_hp_context(); + return AE_NO_MEMORY; } slot->bus = bridge->pci_bus; slot->device = device; INIT_LIST_HEAD(&slot->funcs); - mutex_init(&slot->crit_sect); list_add_tail(&slot->node, &bridge->slots); - /* Register slots for ejectable functions only. */ - if (acpi_pci_check_ejectable(pbus, handle) || is_dock_device(handle)) { + /* + * Expose slots to user space for functions that have _EJ0 or _RMV or + * are located in dock stations. Do not expose them for devices handled + * by the native PCIe hotplug (PCIeHP), becuase that code is supposed to + * expose slots to user space in those cases. + */ + if ((acpi_pci_check_ejectable(pbus, handle) || is_dock_device(adev)) + && !(pdev && device_is_managed_by_native_pciehp(pdev))) { unsigned long long sun; int retval; @@ -381,44 +369,16 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, &val, 60*1000)) slot->flags |= SLOT_ENABLED; - if (is_dock_device(handle)) { - /* we don't want to call this device's _EJ0 - * because we want the dock notify handler - * to call it after it calls _DCK - */ - newfunc->flags &= ~FUNC_HAS_EJ0; - if (register_hotplug_dock_device(handle, - &acpiphp_dock_ops, context, - acpiphp_dock_init, acpiphp_dock_release)) - pr_debug("failed to register dock device\n"); - } - - /* install notify handler */ - if (!(newfunc->flags & FUNC_HAS_DCK)) { - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event, - context); - if (ACPI_FAILURE(status)) - acpi_handle_err(handle, - "failed to install notify handler\n"); - } - return AE_OK; - - err: - mutex_lock(&acpiphp_context_lock); - acpiphp_put_context(context); - mutex_unlock(&acpiphp_context_lock); - return status; } -static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) +static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) { struct acpiphp_context *context; struct acpiphp_bridge *bridge = NULL; - mutex_lock(&acpiphp_context_lock); - context = acpiphp_get_context(handle); + acpi_lock_hp_context(); + context = acpiphp_get_context(adev); if (context) { bridge = context->bridge; if (bridge) @@ -426,7 +386,7 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) acpiphp_put_context(context); } - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); return bridge; } @@ -434,22 +394,15 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) { struct acpiphp_slot *slot; struct acpiphp_func *func; - acpi_status status; list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { - acpi_handle handle = func_to_handle(func); - - if (is_dock_device(handle)) - unregister_hotplug_dock_device(handle); + struct acpi_device *adev = func_to_acpi_device(func); - if (!(func->flags & FUNC_HAS_DCK)) { - status = acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event); - if (ACPI_FAILURE(status)) - pr_err("failed to remove notify handler\n"); - } + acpi_lock_hp_context(); + adev->hp->notify = NULL; + adev->hp->fixup = NULL; + acpi_unlock_hp_context(); } slot->flags |= SLOT_IS_GOING_AWAY; if (slot->slot) @@ -460,9 +413,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_del(&bridge->list); mutex_unlock(&bridge_mutex); - mutex_lock(&acpiphp_context_lock); + acpi_lock_hp_context(); bridge->is_going_away = true; - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); } /** @@ -492,33 +445,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) return max; } -/** - * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree. - * @handle: ACPI device object handle to start from. - */ -static void acpiphp_bus_trim(acpi_handle handle) -{ - struct acpi_device *adev = NULL; - - acpi_bus_get_device(handle, &adev); - if (adev) - acpi_bus_trim(adev); -} - -/** - * acpiphp_bus_add - Scan ACPI namespace subtree. - * @handle: ACPI object handle to start the scan from. - */ -static void acpiphp_bus_add(acpi_handle handle) -{ - struct acpi_device *adev = NULL; - - acpi_bus_scan(handle); - acpi_bus_get_device(handle, &adev); - if (acpi_device_enumerated(adev)) - acpi_device_set_power(adev, ACPI_STATE_D0); -} - static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) { struct acpiphp_func *func; @@ -558,9 +484,13 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot) { struct acpiphp_func *func; - list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_bus_add(func_to_handle(func)); + list_for_each_entry(func, &slot->funcs, sibling) { + struct acpi_device *adev = func_to_acpi_device(func); + acpi_bus_scan(adev->handle); + if (acpi_device_enumerated(adev)) + acpi_device_set_power(adev, ACPI_STATE_D0); + } return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0)); } @@ -625,32 +555,15 @@ static void __ref enable_slot(struct acpiphp_slot *slot) } } -/* return first device in slot, acquiring a reference on it */ -static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) -{ - struct pci_bus *bus = slot->bus; - struct pci_dev *dev; - struct pci_dev *ret = NULL; - - down_read(&pci_bus_sem); - list_for_each_entry(dev, &bus->devices, bus_list) - if (PCI_SLOT(dev->devfn) == slot->device) { - ret = pci_dev_get(dev); - break; - } - up_read(&pci_bus_sem); - - return ret; -} - /** * disable_slot - disable a slot * @slot: ACPI PHP slot */ static void disable_slot(struct acpiphp_slot *slot) { + struct pci_bus *bus = slot->bus; + struct pci_dev *dev, *prev; struct acpiphp_func *func; - struct pci_dev *pdev; /* * enable_slot() enumerates all functions in this device via @@ -658,22 +571,18 @@ static void disable_slot(struct acpiphp_slot *slot) * methods (_EJ0, etc.) or not. Therefore, we remove all functions * here. */ - while ((pdev = dev_in_slot(slot))) { - pci_stop_and_remove_bus_device(pdev); - pci_dev_put(pdev); - } + list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list) + if (PCI_SLOT(dev->devfn) == slot->device) + pci_stop_and_remove_bus_device(dev); list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_bus_trim(func_to_handle(func)); + acpi_bus_trim(func_to_acpi_device(func)); slot->flags &= (~SLOT_ENABLED); } -static bool acpiphp_no_hotplug(acpi_handle handle) +static bool acpiphp_no_hotplug(struct acpi_device *adev) { - struct acpi_device *adev = NULL; - - acpi_bus_get_device(handle, &adev); return adev && adev->flags.no_hotplug; } @@ -682,7 +591,7 @@ static bool slot_no_hotplug(struct acpiphp_slot *slot) struct acpiphp_func *func; list_for_each_entry(func, &slot->funcs, sibling) - if (acpiphp_no_hotplug(func_to_handle(func))) + if (acpiphp_no_hotplug(func_to_acpi_device(func))) return true; return false; @@ -747,28 +656,25 @@ static inline bool device_status_valid(unsigned int sta) */ static void trim_stale_devices(struct pci_dev *dev) { - acpi_handle handle = ACPI_HANDLE(&dev->dev); + struct acpi_device *adev = ACPI_COMPANION(&dev->dev); struct pci_bus *bus = dev->subordinate; bool alive = false; - if (handle) { + if (adev) { acpi_status status; unsigned long long sta; - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) - || acpiphp_no_hotplug(handle); + || acpiphp_no_hotplug(adev); } - if (!alive) { - u32 v; + if (!alive) + alive = pci_device_is_present(dev); - /* Check if the device responds. */ - alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0); - } if (!alive) { pci_stop_and_remove_bus_device(dev); - if (handle) - acpiphp_bus_trim(handle); + if (adev) + acpi_bus_trim(adev); } else if (bus) { struct pci_dev *child, *tmp; @@ -800,7 +706,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) struct pci_bus *bus = slot->bus; struct pci_dev *dev, *tmp; - mutex_lock(&slot->crit_sect); if (slot_no_hotplug(slot)) { ; /* do nothing */ } else if (device_status_valid(get_slot_status(slot))) { @@ -815,7 +720,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) } else { disable_slot(slot); } - mutex_unlock(&slot->crit_sect); } } @@ -855,11 +759,11 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) * ACPI event handlers */ -void acpiphp_check_host_bridge(acpi_handle handle) +void acpiphp_check_host_bridge(struct acpi_device *adev) { struct acpiphp_bridge *bridge; - bridge = acpiphp_handle_to_bridge(handle); + bridge = acpiphp_dev_to_bridge(adev); if (bridge) { pci_lock_rescan_remove(); @@ -872,73 +776,52 @@ void acpiphp_check_host_bridge(acpi_handle handle) static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); -static void hotplug_event(acpi_handle handle, u32 type, void *data) +static void hotplug_event(u32 type, struct acpiphp_context *context) { - struct acpiphp_context *context = data; + acpi_handle handle = context->hp.self->handle; struct acpiphp_func *func = &context->func; + struct acpiphp_slot *slot = func->slot; struct acpiphp_bridge *bridge; - char objname[64]; - struct acpi_buffer buffer = { .length = sizeof(objname), - .pointer = objname }; - mutex_lock(&acpiphp_context_lock); + acpi_lock_hp_context(); bridge = context->bridge; if (bridge) get_bridge(bridge); - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); pci_lock_rescan_remove(); - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ - pr_debug("%s: Bus check notify on %s\n", __func__, objname); - pr_debug("%s: re-enumerating slots under %s\n", - __func__, objname); - if (bridge) { + acpi_handle_debug(handle, "Bus check in %s()\n", __func__); + if (bridge) acpiphp_check_bridge(bridge); - } else { - struct acpiphp_slot *slot = func->slot; - - if (slot->flags & SLOT_IS_GOING_AWAY) - break; - - mutex_lock(&slot->crit_sect); + else if (!(slot->flags & SLOT_IS_GOING_AWAY)) enable_slot(slot); - mutex_unlock(&slot->crit_sect); - } + break; case ACPI_NOTIFY_DEVICE_CHECK: /* device check */ - pr_debug("%s: Device check notify on %s\n", __func__, objname); + acpi_handle_debug(handle, "Device check in %s()\n", __func__); if (bridge) { acpiphp_check_bridge(bridge); - } else { - struct acpiphp_slot *slot = func->slot; - int ret; - - if (slot->flags & SLOT_IS_GOING_AWAY) - break; - + } else if (!(slot->flags & SLOT_IS_GOING_AWAY)) { /* * Check if anything has changed in the slot and rescan * from the parent if that's the case. */ - mutex_lock(&slot->crit_sect); - ret = acpiphp_rescan_slot(slot); - mutex_unlock(&slot->crit_sect); - if (ret) + if (acpiphp_rescan_slot(slot)) acpiphp_check_bridge(func->parent); } break; case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ - pr_debug("%s: Device eject notify on %s\n", __func__, objname); - acpiphp_disable_and_eject_slot(func->slot); + acpi_handle_debug(handle, "Eject request in %s()\n", __func__); + acpiphp_disable_and_eject_slot(slot); break; } @@ -947,106 +830,41 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) put_bridge(bridge); } -static void hotplug_event_work(void *data, u32 type) +static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type) { - struct acpiphp_context *context = data; - acpi_handle handle = context->handle; - - acpi_scan_lock_acquire(); + struct acpiphp_context *context; - hotplug_event(handle, type, context); + context = acpiphp_grab_context(adev); + if (!context) + return -ENODATA; - acpi_scan_lock_release(); - acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); - put_bridge(context->func.parent); + hotplug_event(type, context); + acpiphp_let_context_go(context); + return 0; } /** - * handle_hotplug_event - handle ACPI hotplug event - * @handle: Notify()'ed acpi_handle - * @type: Notify code - * @data: pointer to acpiphp_context structure + * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus. + * @bus: PCI bus to enumerate the slots for. * - * Handles ACPI event notification on slots. - */ -static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) -{ - struct acpiphp_context *context; - u32 ost_code = ACPI_OST_SC_SUCCESS; - acpi_status status; - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - case ACPI_NOTIFY_DEVICE_CHECK: - break; - case ACPI_NOTIFY_EJECT_REQUEST: - ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS; - acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); - break; - - case ACPI_NOTIFY_DEVICE_WAKE: - return; - - case ACPI_NOTIFY_FREQUENCY_MISMATCH: - acpi_handle_err(handle, "Device cannot be configured due " - "to a frequency mismatch\n"); - goto out; - - case ACPI_NOTIFY_BUS_MODE_MISMATCH: - acpi_handle_err(handle, "Device cannot be configured due " - "to a bus mode mismatch\n"); - goto out; - - case ACPI_NOTIFY_POWER_FAULT: - acpi_handle_err(handle, "Device has suffered a power fault\n"); - goto out; - - default: - acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); - ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; - goto out; - } - - mutex_lock(&acpiphp_context_lock); - context = acpiphp_get_context(handle); - if (!context || WARN_ON(context->handle != handle) - || context->func.parent->is_going_away) - goto err_out; - - get_bridge(context->func.parent); - acpiphp_put_context(context); - status = acpi_hotplug_execute(hotplug_event_work, context, type); - if (ACPI_SUCCESS(status)) { - mutex_unlock(&acpiphp_context_lock); - return; - } - put_bridge(context->func.parent); - - err_out: - mutex_unlock(&acpiphp_context_lock); - ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; - - out: - acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); -} - -/* - * Create hotplug slots for the PCI bus. - * It should always return 0 to avoid skipping following notifiers. + * A "slot" is an object associated with a PCI device number. All functions + * (PCI devices) with the same bus and device number belong to the same slot. */ void acpiphp_enumerate_slots(struct pci_bus *bus) { struct acpiphp_bridge *bridge; + struct acpi_device *adev; acpi_handle handle; acpi_status status; if (acpiphp_disabled) return; - handle = ACPI_HANDLE(bus->bridge); - if (!handle) + adev = ACPI_COMPANION(bus->bridge); + if (!adev) return; + handle = adev->handle; bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (!bridge) { acpi_handle_err(handle, "No memory for bridge object\n"); @@ -1074,10 +892,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) * parent is going to be handled by pciehp, in which case this * bridge is not interesting to us either. */ - mutex_lock(&acpiphp_context_lock); - context = acpiphp_get_context(handle); + acpi_lock_hp_context(); + context = acpiphp_get_context(adev); if (!context) { - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); put_device(&bus->dev); pci_dev_put(bridge->pci_dev); kfree(bridge); @@ -1087,17 +905,17 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) context->bridge = bridge; /* Get a reference to the parent bridge. */ get_bridge(context->func.parent); - mutex_unlock(&acpiphp_context_lock); + acpi_unlock_hp_context(); } - /* must be added to the list prior to calling register_slot */ + /* Must be added to the list prior to calling acpiphp_add_context(). */ mutex_lock(&bridge_mutex); list_add(&bridge->list, &bridge_list); mutex_unlock(&bridge_mutex); /* register all slot objects under this bridge */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - register_slot, NULL, bridge, NULL); + acpiphp_add_context, NULL, bridge, NULL); if (ACPI_FAILURE(status)) { acpi_handle_err(handle, "failed to register slots\n"); cleanup_bridge(bridge); @@ -1105,7 +923,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) } } -/* Destroy hotplug slots associated with the PCI bus */ +/** + * acpiphp_remove_slots - Remove slot objects associated with a given bus. + * @bus: PCI bus to remove the slot objects for. + */ void acpiphp_remove_slots(struct pci_bus *bus) { struct acpiphp_bridge *bridge; @@ -1136,13 +957,10 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) if (slot->flags & SLOT_IS_GOING_AWAY) return -ENODEV; - mutex_lock(&slot->crit_sect); /* configure all functions */ if (!(slot->flags & SLOT_ENABLED)) enable_slot(slot); - mutex_unlock(&slot->crit_sect); - pci_unlock_rescan_remove(); return 0; } @@ -1158,8 +976,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) if (slot->flags & SLOT_IS_GOING_AWAY) return -ENODEV; - mutex_lock(&slot->crit_sect); - /* unconfigure all functions */ disable_slot(slot); @@ -1173,7 +989,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) break; } - mutex_unlock(&slot->crit_sect); return 0; } @@ -1181,9 +996,15 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) { int ret; + /* + * Acquire acpi_scan_lock to ensure that the execution of _EJ0 in + * acpiphp_disable_and_eject_slot() will be synchronized properly. + */ + acpi_scan_lock_acquire(); pci_lock_rescan_remove(); ret = acpiphp_disable_and_eject_slot(slot); pci_unlock_rescan_remove(); + acpi_scan_lock_release(); return ret; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 25f0bc659164..d911e0c1f359 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -616,15 +616,11 @@ static int pci_pm_prepare(struct device *dev) int error = 0; /* - * PCI devices suspended at run time need to be resumed at this - * point, because in general it is necessary to reconfigure them for - * system suspend. Namely, if the device is supposed to wake up the - * system from the sleep state, we may need to reconfigure it for this - * purpose. In turn, if the device is not supposed to wake up the - * system from the sleep state, we'll have to prevent it from signaling - * wake-up. + * Devices having power.ignore_children set may still be necessary for + * suspending their children in the next phase of device suspend. */ - pm_runtime_resume(dev); + if (dev->power.ignore_children) + pm_runtime_resume(dev); if (drv && drv->pm && drv->pm->prepare) error = drv->pm->prepare(dev); @@ -654,6 +650,16 @@ static int pci_pm_suspend(struct device *dev) goto Fixup; } + /* + * PCI devices suspended at run time need to be resumed at this point, + * because in general it is necessary to reconfigure them for system + * suspend. Namely, if the device is supposed to wake up the system + * from the sleep state, we may need to reconfigure it for this purpose. + * In turn, if the device is not supposed to wake up the system from the + * sleep state, we'll have to prevent it from signaling wake-up. + */ + pm_runtime_resume(dev); + pci_dev->state_saved = false; if (pm->suspend) { pci_power_t prev = pci_dev->current_state; @@ -808,6 +814,14 @@ static int pci_pm_freeze(struct device *dev) return 0; } + /* + * This used to be done in pci_pm_prepare() for all devices and some + * drivers may depend on it, so do it here. Ideally, runtime-suspended + * devices should not be touched during freeze/thaw transitions, + * however. + */ + pm_runtime_resume(dev); + pci_dev->state_saved = false; if (pm->freeze) { int error; @@ -915,6 +929,9 @@ static int pci_pm_poweroff(struct device *dev) goto Fixup; } + /* The reason to do that is the same as in pci_pm_suspend(). */ + pm_runtime_resume(dev); + pci_dev->state_saved = false; if (pm->poweroff) { int error; diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index 6eecd7cddf57..54d3089d157b 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -125,9 +125,6 @@ sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, if (freqs->new < freqs->old) sa1100_pcmcia_set_mecr(skt, freqs->new); break; - case CPUFREQ_RESUMECHANGE: - sa1100_pcmcia_set_mecr(skt, freqs->new); - break; } return 0; diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 5ae65c11d544..5f67843c7fb7 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -27,8 +27,6 @@ config ACER_WMI depends on ACPI_WMI select INPUT_SPARSEKMAP # Acer WMI depends on ACPI_VIDEO when ACPI is enabled - # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select VIDEO_OUTPUT_CONTROL if ACPI select ACPI_VIDEO if ACPI ---help--- This is a driver for newer Acer (and Wistron) laptops. It adds diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index be02bcc346d3..e6f336270c21 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -66,7 +66,6 @@ #include <linux/backlight.h> #include <linux/input.h> #include <linux/kfifo.h> -#include <linux/video_output.h> #include <linux/platform_device.h> #include <linux/slab.h> #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 3c6768378a94..61b51e17d932 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -834,7 +834,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd, } static const struct x86_cpu_id energy_unit_quirk_ids[] = { - { X86_VENDOR_INTEL, 6, 0x37},/* VLV */ + { X86_VENDOR_INTEL, 6, 0x37},/* Valleyview */ {} }; @@ -947,11 +947,11 @@ static void package_power_limit_irq_restore(int package_id) } static const struct x86_cpu_id rapl_ids[] = { - { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */ - { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */ - { X86_VENDOR_INTEL, 6, 0x37},/* VLV */ - { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */ - { X86_VENDOR_INTEL, 6, 0x45},/* HSW */ + { X86_VENDOR_INTEL, 6, 0x2a},/* Sandy Bridge */ + { X86_VENDOR_INTEL, 6, 0x2d},/* Sandy Bridge EP */ + { X86_VENDOR_INTEL, 6, 0x37},/* Valleyview */ + { X86_VENDOR_INTEL, 6, 0x3a},/* Ivy Bridge */ + { X86_VENDOR_INTEL, 6, 0x45},/* Haswell */ /* TODO: Add more CPU IDs after testing */ {} }; @@ -1147,6 +1147,11 @@ static int rapl_check_domain(int cpu, int domain) if (rdmsrl_safe_on_cpu(cpu, msr, &val1)) return -ENODEV; + /* PP1/uncore/graphics domain may not be active at the time of + * driver loading. So skip further checks. + */ + if (domain == RAPL_DOMAIN_PP1) + return 0; /* energy counters roll slowly on some domains */ while (++retry < 10) { usleep_range(10000, 15000); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index be33d2b0613b..7e0b62602632 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1041,8 +1041,7 @@ static int sci_notifier(struct notifier_block *self, sci_port = container_of(self, struct sci_port, freq_transition); - if ((phase == CPUFREQ_POSTCHANGE) || - (phase == CPUFREQ_RESUMECHANGE)) { + if (phase == CPUFREQ_POSTCHANGE) { struct uart_port *port = &sci_port->port; spin_lock_irqsave(&port->lock, flags); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index dade5b7699bc..97a8f3a12a7b 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -27,12 +27,6 @@ config VGASTATE tristate default n -config VIDEO_OUTPUT_CONTROL - tristate "Lowlevel video output switch controls" - help - This framework adds support for low-level control of the video - output switch. - config VIDEOMODE_HELPERS bool diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ae17ddf49a00..08d6a4ab3ace 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -172,8 +172,6 @@ obj-$(CONFIG_FB_SIMPLE) += simplefb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o -#video output switch sysfs driver -obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o ifeq ($(CONFIG_OF),y) obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o diff --git a/drivers/video/output.c b/drivers/video/output.c deleted file mode 100644 index 1446c49fe6af..000000000000 --- a/drivers/video/output.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * output.c - Display Output Switch driver - * - * Copyright (C) 2006 Luming Yu <luming.yu@intel.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include <linux/module.h> -#include <linux/video_output.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/ctype.h> - - -MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>"); - -static ssize_t state_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ssize_t ret_size = 0; - struct output_device *od = to_output_device(dev); - if (od->props) - ret_size = sprintf(buf,"%.8x\n",od->props->get_status(od)); - return ret_size; -} - -static ssize_t state_store(struct device *dev, struct device_attribute *attr, - const char *buf,size_t count) -{ - char *endp; - struct output_device *od = to_output_device(dev); - int request_state = simple_strtoul(buf,&endp,0); - size_t size = endp - buf; - - if (isspace(*endp)) - size++; - if (size != count) - return -EINVAL; - - if (od->props) { - od->request_state = request_state; - od->props->set_state(od); - } - return count; -} -static DEVICE_ATTR_RW(state); - -static void video_output_release(struct device *dev) -{ - struct output_device *od = to_output_device(dev); - kfree(od); -} - -static struct attribute *video_output_attrs[] = { - &dev_attr_state.attr, - NULL, -}; -ATTRIBUTE_GROUPS(video_output); - -static struct class video_output_class = { - .name = "video_output", - .dev_release = video_output_release, - .dev_groups = video_output_groups, -}; - -struct output_device *video_output_register(const char *name, - struct device *dev, - void *devdata, - struct output_properties *op) -{ - struct output_device *new_dev; - int ret_code = 0; - - new_dev = kzalloc(sizeof(struct output_device),GFP_KERNEL); - if (!new_dev) { - ret_code = -ENOMEM; - goto error_return; - } - new_dev->props = op; - new_dev->dev.class = &video_output_class; - new_dev->dev.parent = dev; - dev_set_name(&new_dev->dev, "%s", name); - dev_set_drvdata(&new_dev->dev, devdata); - ret_code = device_register(&new_dev->dev); - if (ret_code) { - kfree(new_dev); - goto error_return; - } - return new_dev; - -error_return: - return ERR_PTR(ret_code); -} -EXPORT_SYMBOL(video_output_register); - -void video_output_unregister(struct output_device *dev) -{ - if (!dev) - return; - device_unregister(&dev->dev); -} -EXPORT_SYMBOL(video_output_unregister); - -static void __exit video_output_class_exit(void) -{ - class_unregister(&video_output_class); -} - -static int __init video_output_class_init(void) -{ - return class_register(&video_output_class); -} - -postcore_initcall(video_output_class_init); -module_exit(video_output_class_exit); diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index 80875fb770ed..3e62ee4b3b66 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c @@ -313,7 +313,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, goto out; } - (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); + (void) acpi_evaluate_ost(handle, event, ost_code, NULL); out: acpi_scan_lock_release(); diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c index f8d18626969a..34e40b733f9a 100644 --- a/drivers/xen/xen-acpi-memhotplug.c +++ b/drivers/xen/xen-acpi-memhotplug.c @@ -285,7 +285,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) return; } - (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); + (void) acpi_evaluate_ost(handle, event, ost_code, NULL); return; } diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c index 40c4bc06b5fa..f83b754505f8 100644 --- a/drivers/xen/xen-acpi-pad.c +++ b/drivers/xen/xen-acpi-pad.c @@ -77,27 +77,14 @@ static int acpi_pad_pur(acpi_handle handle) return num; } -/* Notify firmware how many CPUs are idle */ -static void acpi_pad_ost(acpi_handle handle, int stat, - uint32_t idle_nums) -{ - union acpi_object params[3] = { - {.type = ACPI_TYPE_INTEGER,}, - {.type = ACPI_TYPE_INTEGER,}, - {.type = ACPI_TYPE_BUFFER,}, - }; - struct acpi_object_list arg_list = {3, params}; - - params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY; - params[1].integer.value = stat; - params[2].buffer.length = 4; - params[2].buffer.pointer = (void *)&idle_nums; - acpi_evaluate_object(handle, "_OST", &arg_list, NULL); -} - static void acpi_pad_handle_notify(acpi_handle handle) { int idle_nums; + struct acpi_buffer param = { + .length = 4, + .pointer = (void *)&idle_nums, + }; + mutex_lock(&xen_cpu_lock); idle_nums = acpi_pad_pur(handle); @@ -109,7 +96,8 @@ static void acpi_pad_handle_notify(acpi_handle handle) idle_nums = xen_acpi_pad_idle_cpus(idle_nums) ?: xen_acpi_pad_idle_cpus_num(); if (idle_nums >= 0) - acpi_pad_ost(handle, 0, idle_nums); + acpi_evaluate_ost(handle, ACPI_PROCESSOR_AGGREGATOR_NOTIFY, + 0, ¶m); mutex_unlock(&xen_cpu_lock); } |