diff options
120 files changed, 5084 insertions, 1495 deletions
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index a9adad828cdc..c6279c2be47c 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -51,9 +51,6 @@ Typical usage of the OPP library is as follows: SoC framework -> modifies on required cases certain OPPs -> OPP layer -> queries to search/retrieve information -> -Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP -to make the OPP layer available. - OPP layer expects each domain to be represented by a unique device pointer. SoC framework registers a set of initial OPPs per device with the OPP layer. This list is expected to be an optimally small number typically around 5 per device. diff --git a/MAINTAINERS b/MAINTAINERS index e33ca844f352..05e545096100 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2556,8 +2556,8 @@ F: arch/x86/kernel/cpuid.c F: arch/x86/kernel/msr.c CPU POWER MONITORING SUBSYSTEM -M: Dominik Brodowski <linux@dominikbrodowski.net> M: Thomas Renninger <trenn@suse.de> +L: linux-pm@vger.kernel.org S: Maintained F: tools/power/cpupower/ @@ -7066,8 +7066,10 @@ F: include/linux/timer* F: kernel/time/*timer* POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS +M: Sebastian Reichel <sre@kernel.org> M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> M: David Woodhouse <dwmw2@infradead.org> +L: linux-pm@vger.kernel.org T: git git://git.infradead.org/battery-2.6.git S: Maintained F: include/linux/power_supply.h diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 5d4ff6571dcd..2d0240f241b8 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -100,7 +100,6 @@ config SOC_EXYNOS5440 default y depends on ARCH_EXYNOS5 select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - select ARCH_HAS_OPP select HAVE_ARM_ARCH_TIMER select AUTO_ZRELADDR select MIGHT_HAVE_PCI diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig index a5960e2ac090..31aa866c3317 100644 --- a/arch/arm/mach-highbank/Kconfig +++ b/arch/arm/mach-highbank/Kconfig @@ -2,7 +2,6 @@ config ARCH_HIGHBANK bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7 select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_HAS_OPP select ARCH_SUPPORTS_BIG_ENDIAN select ARM_AMBA select ARM_ERRATA_764369 if SMP diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 4b5185748f74..ab6bcfd2e220 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -1,6 +1,5 @@ menuconfig ARCH_MXC bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 - select ARCH_HAS_OPP select ARCH_REQUIRE_GPIOLIB select ARM_CPU_SUSPEND if PM select CLKSRC_MMIO diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1c1ed737f7ab..e7189dcc9309 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -15,7 +15,6 @@ config ARCH_OMAP3 bool "TI OMAP3" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS - select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select OMAP_INTERCONNECT select PM_OPP if PM diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 798073057e51..3a6e3c20a86d 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -85,7 +85,6 @@ config ARCH_R8A73A4 select CPU_V7 select SH_CLK_CPG select RENESAS_IRQC - select ARCH_HAS_OPP select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_TMU @@ -263,7 +262,6 @@ config MACH_KOELSCH config MACH_KZM9G bool "KZM-A9-GT board" depends on ARCH_SH73A0 - select ARCH_HAS_OPP select ARCH_REQUIRE_GPIOLIB select REGULATOR_FIXED_VOLTAGE if REGULATOR select SND_SOC_AK4642 if SND_SIMPLE_CARD diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index d8b9330f896a..1af70329b88d 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -64,7 +64,6 @@ config ARCH_VEXPRESS_DCSCB config ARCH_VEXPRESS_SPC bool "Versatile Express Serial Power Controller (SPC)" - select ARCH_HAS_OPP select PM_OPP help The TC2 (A15x2 A7x3) versatile express core tile integrates a logic diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 0c164f81e72d..aaa5162c1509 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -1,6 +1,5 @@ config ARCH_ZYNQ bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7 - select ARCH_HAS_OPP select ARCH_SUPPORTS_BIG_ENDIAN select ARM_AMBA select ARM_GIC diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 2f3abcf8f6bc..44a6915ab13d 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -10,6 +10,7 @@ config IA64 select ARCH_MIGHT_HAVE_PC_SERIO select PCI if (!IA64_HP_SIM) select ACPI if (!IA64_HP_SIM) + select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI select PM if (!IA64_HP_SIM) select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_IDE diff --git a/arch/ia64/include/asm/acenv.h b/arch/ia64/include/asm/acenv.h index 3f9eaeec9873..35ff13afbf34 100644 --- a/arch/ia64/include/asm/acenv.h +++ b/arch/ia64/include/asm/acenv.h @@ -19,8 +19,6 @@ /* Asm macros */ -#ifdef CONFIG_ACPI - static inline int ia64_acpi_acquire_global_lock(unsigned int *lock) { @@ -51,6 +49,4 @@ ia64_acpi_release_global_lock(unsigned int *lock) #define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \ ((Acq) = ia64_acpi_release_global_lock(&facs->global_lock)) -#endif - #endif /* _ASM_IA64_ACENV_H */ diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 75dc59a793d6..a1d91ab4c5ef 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -40,6 +40,11 @@ extern int acpi_lapic; #define acpi_noirq 0 /* ACPI always enabled on IA64 */ #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */ #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ + +static inline bool acpi_has_cpu_in_madt(void) +{ + return !!acpi_lapic; +} #endif #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ static inline void disable_acpi(void) { } diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6cfeb082a422..bf2405053af5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -21,6 +21,7 @@ config X86_64 ### Arch settings config X86 def_bool y + select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO @@ -133,6 +134,7 @@ config X86 select ARCH_SUPPORTS_ATOMIC_RMW select HAVE_ACPI_APEI if ACPI select HAVE_ACPI_APEI_NMI if ACPI + select ACPI_LEGACY_TABLES_LOOKUP if ACPI config INSTRUCTION_DECODER def_bool y diff --git a/arch/x86/include/asm/acenv.h b/arch/x86/include/asm/acenv.h index 66873297e9f5..1b010a859b8b 100644 --- a/arch/x86/include/asm/acenv.h +++ b/arch/x86/include/asm/acenv.h @@ -18,8 +18,6 @@ #define ACPI_FLUSH_CPU_CACHE() wbinvd() -#ifdef CONFIG_ACPI - int __acpi_acquire_global_lock(unsigned int *lock); int __acpi_release_global_lock(unsigned int *lock); @@ -44,6 +42,4 @@ int __acpi_release_global_lock(unsigned int *lock); : "=r"(n_hi), "=r"(n_lo) \ : "0"(n_hi), "1"(n_lo)) -#endif - #endif /* _ASM_X86_ACENV_H */ diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index e06225eda635..0ab4f9fd2687 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -121,6 +121,11 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf) buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); } +static inline bool acpi_has_cpu_in_madt(void) +{ + return !!acpi_lapic; +} + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 206942b8d105..d0f3265fb85d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -42,6 +42,12 @@ menuconfig ACPI if ACPI +config ACPI_LEGACY_TABLES_LOOKUP + bool + +config ARCH_MIGHT_HAVE_ACPI_PDC + bool + config ACPI_SLEEP bool depends on SUSPEND || HIBERNATION diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index ea55e0179f81..505d4d79fe3e 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -36,6 +36,7 @@ acpi-y += scan.o acpi-y += resource.o acpi-y += acpi_processor.o acpi-y += processor_core.o +acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index 0ad6f389d922..b3842ffc19ba 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c @@ -71,11 +71,11 @@ static u32 l1_percpu_entry; #define ELOG_ENTRY_ADDR(phyaddr) \ (phyaddr - elog_base + (u8 *)elog_addr) -static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) +static struct acpi_hest_generic_status *extlog_elog_entry_check(int cpu, int bank) { int idx; u64 data; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; WARN_ON(cpu < 0); idx = ELOG_IDX(cpu, bank); @@ -84,7 +84,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) return NULL; data &= EXT_ELOG_ENTRY_MASK; - estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data); + estatus = (struct acpi_hest_generic_status *)ELOG_ENTRY_ADDR(data); /* if no valid data in elog entry, just return */ if (estatus->block_status == 0) @@ -94,7 +94,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) } static void __print_extlog_rcd(const char *pfx, - struct acpi_generic_status *estatus, int cpu) + struct acpi_hest_generic_status *estatus, int cpu) { static atomic_t seqno; unsigned int curr_seqno; @@ -113,7 +113,7 @@ static void __print_extlog_rcd(const char *pfx, } static int print_extlog_rcd(const char *pfx, - struct acpi_generic_status *estatus, int cpu) + struct acpi_hest_generic_status *estatus, int cpu) { /* Not more than 2 messages every 5 seconds */ static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); @@ -139,8 +139,8 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, struct mce *mce = (struct mce *)data; int bank = mce->bank; int cpu = mce->extcpu; - struct acpi_generic_status *estatus, *tmp; - struct acpi_generic_data *gdata; + struct acpi_hest_generic_status *estatus, *tmp; + struct acpi_hest_generic_data *gdata; const uuid_le *fru_id = &NULL_UUID_LE; char *fru_text = ""; uuid_le *sec_type; @@ -154,7 +154,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, /* clear record status to enable BIOS to update it again */ estatus->block_status = 0; - tmp = (struct acpi_generic_status *)elog_buf; + tmp = (struct acpi_hest_generic_status *)elog_buf; if (!ras_userspace_consumers()) { print_extlog_rcd(NULL, tmp, cpu); @@ -163,7 +163,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, /* log event via trace */ err_seq++; - gdata = (struct acpi_generic_data *)(tmp + 1); + gdata = (struct acpi_hest_generic_data *)(tmp + 1); if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) fru_id = (uuid_le *)gdata->fru_id; if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 9cb65b0e7597..ce06149088c5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -113,6 +113,14 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata) writel(val, pdata->mmio_base + offset); } +static struct lpss_device_desc wpt_dev_desc = { + .clk_required = true, + .prv_offset = 0x800, + .ltr_required = true, + .clk_divider = true, + .clk_gate = true, +}; + static struct lpss_device_desc lpt_dev_desc = { .clk_required = true, .prv_offset = 0x800, @@ -226,6 +234,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, { "INT3437", }, + { "INT3438", LPSS_ADDR(wpt_dev_desc) }, + { } }; diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 4ddb0dca56f6..996fa1959eea 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -12,6 +12,7 @@ #include <linux/acpi.h> #include <linux/module.h> +#include <linux/ctype.h> static const struct acpi_device_id acpi_pnp_device_ids[] = { /* soc_button_array */ @@ -320,11 +321,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {""}, }; -static bool is_hex_digit(char c) -{ - return (c >= 0 && c <= '9') || (c >= 'A' && c <= 'F'); -} - static bool matching_id(char *idstr, char *list_id) { int i; @@ -335,7 +331,7 @@ static bool matching_id(char *idstr, char *list_id) for (i = 3; i < 7; i++) { char c = toupper(idstr[i]); - if (!is_hex_digit(c) + if (!isxdigit(c) || (list_id[i] != 'X' && c != toupper(list_id[i]))) return false; } diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 1c085742644f..1fdf5e07a1c7 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -268,7 +268,7 @@ static int acpi_processor_get_info(struct acpi_device *device) pr->apic_id = apic_id; cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); - if (!cpu0_initialized && !acpi_lapic) { + if (!cpu0_initialized && !acpi_has_cpu_in_madt()) { cpu0_initialized = 1; /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if ((cpu_index == -1) && (num_online_cpus() == 1)) diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 8bb43f06e11f..c1a963581dc0 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -2,7 +2,7 @@ # Makefile for ACPICA Core interpreter # -ccflags-y := -Os +ccflags-y := -Os -DBUILDING_ACPICA ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # use acpi.o to put all files here into acpi.o modparam namespace @@ -157,6 +157,7 @@ acpi-y += \ uterror.o \ uteval.o \ utglobal.o \ + uthex.o \ utids.o \ utinit.o \ utlock.o \ @@ -175,5 +176,10 @@ acpi-y += \ utxferror.o \ utxfmutex.o -acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o +acpi-$(ACPI_FUTURE_USAGE) += \ + utcache.o \ + utfileio.o \ + utprint.o \ + uttrack.o \ + utuuid.o diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index 8698ffba6f39..3d2c88289da9 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h @@ -79,10 +79,13 @@ /* Macros for usage messages */ #define ACPI_USAGE_HEADER(usage) \ - printf ("Usage: %s\nOptions:\n", usage); + acpi_os_printf ("Usage: %s\nOptions:\n", usage); + +#define ACPI_USAGE_TEXT(description) \ + acpi_os_printf (description); #define ACPI_OPTION(name, description) \ - printf (" %-18s%s\n", name, description); + acpi_os_printf (" %-18s%s\n", name, description); #define FILE_SUFFIX_DISASSEMBLY "dsl" #define ACPI_TABLE_FILE_SUFFIX ".dat" @@ -102,7 +105,7 @@ extern char *acpi_gbl_optarg; /* * cmfsize - Common get file size function */ -u32 cm_get_file_size(FILE * file); +u32 cm_get_file_size(ACPI_FILE file); #ifndef ACPI_DUMP_APP /* diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 68a91eb0fa48..1d026ff1683f 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -233,9 +233,6 @@ acpi_status acpi_db_load_acpi_table(char *filename); acpi_status acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table); -acpi_status -acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table); - /* * dbhistry - debugger HISTORY command */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 115eedcade1e..ebf02cc10a43 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -297,7 +297,7 @@ ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); * ****************************************************************************/ -ACPI_GLOBAL(u8, acpi_gbl_db_output_flags); +ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT); #ifdef ACPI_DISASSEMBLER @@ -362,6 +362,12 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects); #ifdef ACPI_APPLICATION ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); +ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL); + +/* Print buffer */ + +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */ +ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]); #endif /* ACPI_APPLICATION */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 91f801a2e689..1f9aba5fb81f 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -730,12 +730,13 @@ union acpi_parse_value { #define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ #define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ #define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ -#define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */ -#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */ -#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */ -#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */ -#define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */ -#define ACPI_DASM_IGNORE 0x0A /* Not used at this time */ +#define ACPI_DASM_UUID 0x05 /* Buffer is a UUID/GUID */ +#define ACPI_DASM_EISAID 0x06 /* Integer is an EISAID */ +#define ACPI_DASM_MATCHOP 0x07 /* Parent opcode is a Match() operator */ +#define ACPI_DASM_LNOT_PREFIX 0x08 /* Start of a Lnot_equal (etc.) pair of opcodes */ +#define ACPI_DASM_LNOT_SUFFIX 0x09 /* End of a Lnot_equal (etc.) pair of opcodes */ +#define ACPI_DASM_HID_STRING 0x0A /* String is a _HID or _CID */ +#define ACPI_DASM_IGNORE 0x0B /* Not used at this time */ /* * Generic operation (for example: If, While, Store) @@ -1154,4 +1155,9 @@ struct ah_device_id { char *description; }; +struct ah_uuid { + char *description; + char *string; +}; + #endif /* __ACLOCAL_H__ */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index bd08817cafd8..bd3908d26c4f 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -105,6 +105,11 @@ * count = 0 (optional) * (Used for _DLM) * + * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID + * defines the format of the package. Zero-length parent package is + * allowed. + * (Used for _DSD) + * *****************************************************************************/ enum acpi_return_package_types { @@ -117,7 +122,8 @@ enum acpi_return_package_types { ACPI_PTYPE2_FIXED = 7, ACPI_PTYPE2_MIN = 8, ACPI_PTYPE2_REV_FIXED = 9, - ACPI_PTYPE2_FIX_VAR = 10 + ACPI_PTYPE2_FIX_VAR = 10, + ACPI_PTYPE2_UUID_PAIR = 11 }; /* Support macros for users of the predefined info table */ @@ -364,6 +370,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_CBA", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */ + {{"_CCA", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 5.1 */ + {{"_CDM", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -436,6 +445,11 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, + {{"_DSD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ + PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, + ACPI_RTYPE_PACKAGE, 1, 0), + {{"_DSM", METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_PACKAGE), diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 1e256c5bda20..486d342e74b6 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -95,7 +95,6 @@ extern const char *acpi_gbl_pt_decode[]; #ifdef ACPI_ASL_COMPILER #include <stdio.h> -extern FILE *acpi_gbl_output_file; #define ACPI_MSG_REDIRECT_BEGIN \ FILE *output_file = acpi_gbl_output_file; \ @@ -195,6 +194,8 @@ char *acpi_ut_get_event_name(u32 event_id); char acpi_ut_hex_to_ascii_char(u64 integer, u32 position); +u8 acpi_ut_ascii_char_to_hex(int hex_char); + u8 acpi_ut_valid_object_type(acpi_object_type type); /* @@ -211,6 +212,8 @@ void acpi_ut_subsystem_shutdown(void); acpi_size acpi_ut_strlen(const char *string); +char *acpi_ut_strchr(const char *string, int ch); + char *acpi_ut_strcpy(char *dst_string, const char *src_string); char *acpi_ut_strncpy(char *dst_string, @@ -257,7 +260,7 @@ extern const u8 _acpi_ctype[]; #define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) #define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) #define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) -#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) +#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) #endif /* !ACPI_USE_SYSTEM_CLIBRARY */ @@ -352,6 +355,13 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id); void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); +#ifdef ACPI_APPLICATION +void +acpi_ut_dump_buffer_to_file(ACPI_FILE file, + u8 *buffer, + u32 count, u32 display, u32 base_offset); +#endif + void acpi_ut_report_error(char *module_name, u32 line_number); void acpi_ut_report_info(char *module_name, u32 line_number); @@ -394,6 +404,14 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, u8 method_count, u8 *out_values); /* + * utfileio - file operations + */ +#ifdef ACPI_APPLICATION +acpi_status +acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table); +#endif + +/* * utids - device ID support */ acpi_status @@ -743,4 +761,30 @@ const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg); const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); +const char *acpi_ah_match_uuid(u8 *data); + +/* + * utprint - printf/vprintf output functions + */ +const char *acpi_ut_scan_number(const char *string, u64 *number_ptr); + +const char *acpi_ut_print_number(char *string, u64 number); + +int +acpi_ut_vsnprintf(char *string, + acpi_size size, const char *format, va_list args); + +int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...); + +#ifdef ACPI_APPLICATION +int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args); + +int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...); +#endif + +/* + * utuuid -- UUID support functions + */ +void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer); + #endif /* _ACUTILS_H */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 48f70013b488..e4ba4dec86af 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -698,21 +698,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, } /* - * If edge-triggered, clear the GPE status bit now. Note that - * level-triggered events are cleared after the GPE is serviced. - */ - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_EDGE_TRIGGERED) { - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE %02X", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - } - - /* * Always disable the GPE so that it does not keep firing before * any asynchronous activity completes (either from the execution * of a GPE method or an asynchronous GPE handler.) @@ -729,6 +714,23 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, } /* + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced. + */ + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_EDGE_TRIGGERED) { + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE %02X", + gpe_number)); + (void)acpi_hw_low_set_gpe(gpe_event_info, + ACPI_GPE_CONDITIONAL_ENABLE); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + } + + /* * Dispatch the GPE to either an installed handler or the control * method associated with this GPE (_Lxx or _Exx). If a handler * exists, we invoke it and do not attempt to run the method. diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index cb534faf5369..0cf159cc6e6d 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -126,11 +126,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - /* Ensure that we have a valid GPE number */ - + /* + * Ensure that we have a valid GPE number and that there is some way + * of handling the GPE (handler or a GPE method). In other words, we + * won't allow a valid GPE to be enabled if there is no way to handle it. + */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { - status = acpi_ev_add_gpe_reference(gpe_event_info); + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != + ACPI_GPE_DISPATCH_NONE) { + status = acpi_ev_add_gpe_reference(gpe_event_info); + } else { + status = AE_NO_HANDLER; + } } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); @@ -179,6 +187,53 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) /******************************************************************************* * + * FUNCTION: acpi_mark_gpe_for_wake + * + * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 + * gpe_number - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply + * sets the ACPI_GPE_CAN_WAKE flag. + * + * Some potential callers of acpi_setup_gpe_for_wake may know in advance that + * there won't be any notify handlers installed for device wake notifications + * from the given GPE (one example is a button GPE in Linux). For these cases, + * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake. + * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to + * setup implicit wake notification for it (since there's no handler method). + * + ******************************************************************************/ +acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) +{ + struct acpi_gpe_event_info *gpe_event_info; + acpi_status status = AE_BAD_PARAMETER; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (gpe_event_info) { + + /* Mark the GPE as a possible wake event */ + + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; + status = AE_OK; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake) + +/******************************************************************************* + * * FUNCTION: acpi_setup_gpe_for_wake * * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index 4cfc3d3b5c97..6fbfad47518c 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -75,6 +75,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index) { u32 i; + u32 timer; ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); @@ -86,11 +87,19 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } /* + * We will emit the current timer value (in microseconds) with each + * debug output. Only need the lower 26 bits. This allows for 67 + * million microseconds or 67 seconds before rollover. + */ + timer = ((u32)acpi_os_get_timer() / 10); /* (100 nanoseconds to microseconds) */ + timer &= 0x03FFFFFF; + + /* * Print line header as long as we are not in the middle of an * object display */ if (!((level > 0) && index == 0)) { - acpi_os_printf("[ACPI Debug] %*s", level, " "); + acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " "); } /* Display the index for package output only */ diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 925202acc3e4..0f23c3f2678e 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -494,7 +494,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, } } - acpi_os_printf("\n", next); + acpi_os_printf("\n"); break; case ACPI_EXD_HDLR_LIST: @@ -528,7 +528,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, } } - acpi_os_printf("\n", next); + acpi_os_printf("\n"); break; case ACPI_EXD_RGN_LIST: @@ -562,7 +562,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, } } - acpi_os_printf("\n", next); + acpi_os_printf("\n"); break; case ACPI_EXD_NODE: diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 12878e1982f7..6907ce0c704c 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -56,7 +56,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); /******************************************************************************* * - * FUNCTION: acpi_get_serial_access_bytes + * FUNCTION: acpi_ex_get_serial_access_length * * PARAMETERS: accessor_type - The type of the protocol indicated by region * field access attributes @@ -103,7 +103,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) case AML_FIELD_ATTRIB_BLOCK_CALL: default: - length = ACPI_GSBUS_BUFFER_SIZE; + length = ACPI_GSBUS_BUFFER_SIZE - 2; break; } @@ -186,12 +186,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, access_length); /* - * Add additional 2 bytes for modeled generic_serial_bus data buffer: - * typedef struct { - * BYTEStatus; // Byte 0 of the data buffer - * BYTELength; // Byte 1 of the data buffer - * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, - * } + * Add additional 2 bytes for the generic_serial_bus data buffer: + * + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) */ length += 2; function = ACPI_READ | (accessor_type << 16); @@ -368,12 +367,11 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, access_length); /* - * Add additional 2 bytes for modeled generic_serial_bus data buffer: - * typedef struct { - * BYTEStatus; // Byte 0 of the data buffer - * BYTELength; // Byte 1 of the data buffer - * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, - * } + * Add additional 2 bytes for the generic_serial_bus data buffer: + * + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) */ length += 2; function = ACPI_WRITE | (accessor_type << 16); diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index e0fd9b4978cd..a4c34d2c556b 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -278,8 +278,9 @@ acpi_status acpi_hw_clear_acpi_status(void) acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { goto exit; + } /* Clear the GPE Bits in all GPE registers in all GPE blocks */ diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index fe54a8c73b8c..a42ee9d6970d 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -237,6 +237,16 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } + + /* + * Detach the object from any data objects (which are still held by + * the namespace node) + */ + if (obj_desc->common.next_object && + ((obj_desc->common.next_object)->common.type == + ACPI_TYPE_LOCAL_DATA)) { + obj_desc->common.next_object = NULL; + } } /* Reset the node type to untyped */ diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c index 3c1699740653..038ea887f562 100644 --- a/drivers/acpi/acpica/utbuffer.c +++ b/drivers/acpi/acpica/utbuffer.c @@ -199,3 +199,131 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) acpi_ut_dump_buffer(buffer, count, display, 0); } + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer_to_file + * + * PARAMETERS: file - File descriptor + * buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * base_offset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii to a file. + * + ******************************************************************************/ + +void +acpi_ut_dump_buffer_to_file(ACPI_FILE file, + u8 *buffer, u32 count, u32 display, u32 base_offset) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + if (!buffer) { + acpi_ut_file_printf(file, + "Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((count < 4) || (count & 0x01)) { + display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < count) { + + /* Print current offset */ + + acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i)); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + + /* Dump fill spaces */ + + acpi_ut_file_printf(file, "%*s", + ((display * 2) + 1), " "); + j += display; + continue; + } + + switch (display) { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + acpi_ut_file_printf(file, "%02X ", + buffer[(acpi_size) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%04X ", temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%08X ", temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%08X", temp32); + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j + + 4]); + acpi_ut_file_printf(file, "%08X ", temp32); + break; + } + + j += display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + acpi_ut_file_printf(file, " "); + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_ut_file_printf(file, "\n"); + return; + } + + buf_char = buffer[(acpi_size) i + j]; + if (ACPI_IS_PRINT(buf_char)) { + acpi_ut_file_printf(file, "%c", buf_char); + } else { + acpi_ut_file_printf(file, "."); + } + } + + /* Done with that line. */ + + acpi_ut_file_printf(file, "\n"); + i += 16; + } + + return; +} +#endif diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 270c16464dd9..ff601c0f7c7a 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, status = acpi_ut_copy_simple_object(source_desc, *dest_desc); } + /* Delete the allocated object if copy failed */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(*dest_desc); + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 21a20ac5b1e1..e516254c63b2 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -561,3 +561,29 @@ acpi_ut_ptr_exit(u32 line_number, } #endif + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_log_error + * + * PARAMETERS: format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message to the console, used by applications. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...) +{ + va_list args; + + va_start(args, format); + (void)acpi_ut_file_vprintf(ACPI_FILE_ERR, format, args); + va_end(args); +} + +ACPI_EXPORT_SYMBOL(acpi_log_error) +#endif diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 90ec37c473c6..40e923e675fc 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -88,33 +88,6 @@ const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { /******************************************************************************* * - * FUNCTION: acpi_ut_hex_to_ascii_char - * - * PARAMETERS: integer - Contains the hex digit - * position - bit position of the digit within the - * integer (multiple of 4) - * - * RETURN: The converted Ascii character - * - * DESCRIPTION: Convert a hex digit to an Ascii character - * - ******************************************************************************/ - -/* Hex to ASCII conversion table */ - -static const char acpi_gbl_hex_to_ascii[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) -{ - - return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); -} - -/******************************************************************************* - * * FUNCTION: acpi_ut_get_region_name * * PARAMETERS: Space ID - ID for the region @@ -475,7 +448,8 @@ static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = { /* 09 */ "Device PLD Check", /* 0A */ "Reserved", /* 0B */ "System Locality Update", - /* 0C */ "Shutdown Request" + /* 0C */ "Shutdown Request", + /* 0D */ "System Resource Affinity Update" }; static const char *acpi_gbl_device_notify[4] = { @@ -502,7 +476,7 @@ static const char *acpi_gbl_thermal_notify[4] = { const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type) { - /* 00 - 0C are common to all object types */ + /* 00 - 0D are common to all object types */ if (notify_value <= ACPI_NOTIFY_MAX) { return (acpi_gbl_generic_notify[notify_value]); diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c new file mode 100644 index 000000000000..4e263a8cc6f0 --- /dev/null +++ b/drivers/acpi/acpica/utfileio.c @@ -0,0 +1,331 @@ +/******************************************************************************* + * + * Module Name: utfileio - simple file I/O routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "actables.h" +#include "acapps.h" + +#ifdef ACPI_ASL_COMPILER +#include "aslcompiler.h" +#endif + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("utfileio") + +#ifdef ACPI_APPLICATION +/* Local prototypes */ +static acpi_status +acpi_ut_check_text_mode_corruption(u8 *table, + u32 table_length, u32 file_length); + +static acpi_status +acpi_ut_read_table(FILE * fp, + struct acpi_table_header **table, u32 *table_length); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_check_text_mode_corruption + * + * PARAMETERS: table - Table buffer + * table_length - Length of table from the table header + * file_length - Length of the file that contains the table + * + * RETURN: Status + * + * DESCRIPTION: Check table for text mode file corruption where all linefeed + * characters (LF) have been replaced by carriage return linefeed + * pairs (CR/LF). + * + ******************************************************************************/ + +static acpi_status +acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length) +{ + u32 i; + u32 pairs = 0; + + if (table_length != file_length) { + ACPI_WARNING((AE_INFO, + "File length (0x%X) is not the same as the table length (0x%X)", + file_length, table_length)); + } + + /* Scan entire table to determine if each LF has been prefixed with a CR */ + + for (i = 1; i < file_length; i++) { + if (table[i] == 0x0A) { + if (table[i - 1] != 0x0D) { + + /* The LF does not have a preceding CR, table not corrupted */ + + return (AE_OK); + } else { + /* Found a CR/LF pair */ + + pairs++; + } + i++; + } + } + + if (!pairs) { + return (AE_OK); + } + + /* + * Entire table scanned, each CR is part of a CR/LF pair -- + * meaning that the table was treated as a text file somewhere. + * + * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the + * original table are left untouched by the text conversion process -- + * meaning that we cannot simply replace CR/LF pairs with LFs. + */ + acpi_os_printf("Table has been corrupted by text mode conversion\n"); + acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs); + acpi_os_printf("Table cannot be repaired!\n"); + return (AE_BAD_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_read_table + * + * PARAMETERS: fp - File that contains table + * table - Return value, buffer with table + * table_length - Return value, length of table + * + * RETURN: Status + * + * DESCRIPTION: Load the DSDT from the file pointer + * + ******************************************************************************/ + +static acpi_status +acpi_ut_read_table(FILE * fp, + struct acpi_table_header **table, u32 *table_length) +{ + struct acpi_table_header table_header; + u32 actual; + acpi_status status; + u32 file_size; + u8 standard_header = TRUE; + s32 count; + + /* Get the file size */ + + file_size = cm_get_file_size(fp); + if (file_size == ACPI_UINT32_MAX) { + return (AE_ERROR); + } + + if (file_size < 4) { + return (AE_BAD_HEADER); + } + + /* Read the signature */ + + fseek(fp, 0, SEEK_SET); + + count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); + if (count != sizeof(struct acpi_table_header)) { + acpi_os_printf("Could not read the table header\n"); + return (AE_BAD_HEADER); + } + + /* The RSDP table does not have standard ACPI header */ + + if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) { + *table_length = file_size; + standard_header = FALSE; + } else { + +#if 0 + /* Validate the table header/length */ + + status = acpi_tb_validate_table_header(&table_header); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Table header is invalid!\n"); + return (status); + } +#endif + + /* File size must be at least as long as the Header-specified length */ + + if (table_header.length > file_size) { + acpi_os_printf + ("TableHeader length [0x%X] greater than the input file size [0x%X]\n", + table_header.length, file_size); + +#ifdef ACPI_ASL_COMPILER + status = fl_check_for_ascii(fp, NULL, FALSE); + if (ACPI_SUCCESS(status)) { + acpi_os_printf + ("File appears to be ASCII only, must be binary\n"); + } +#endif + return (AE_BAD_HEADER); + } +#ifdef ACPI_OBSOLETE_CODE + /* We only support a limited number of table types */ + + if (!ACPI_COMPARE_NAME + ((char *)table_header.signature, ACPI_SIG_DSDT) + && !ACPI_COMPARE_NAME((char *)table_header.signature, + ACPI_SIG_PSDT) + && !ACPI_COMPARE_NAME((char *)table_header.signature, + ACPI_SIG_SSDT)) { + acpi_os_printf + ("Table signature [%4.4s] is invalid or not supported\n", + (char *)table_header.signature); + ACPI_DUMP_BUFFER(&table_header, + sizeof(struct acpi_table_header)); + return (AE_ERROR); + } +#endif + + *table_length = table_header.length; + } + + /* Allocate a buffer for the table */ + + *table = acpi_os_allocate((size_t) file_size); + if (!*table) { + acpi_os_printf + ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", + table_header.signature, *table_length); + return (AE_NO_MEMORY); + } + + /* Get the rest of the table */ + + fseek(fp, 0, SEEK_SET); + actual = fread(*table, 1, (size_t) file_size, fp); + if (actual == file_size) { + if (standard_header) { + + /* Now validate the checksum */ + + status = acpi_tb_verify_checksum((void *)*table, + ACPI_CAST_PTR(struct + acpi_table_header, + *table)-> + length); + + if (status == AE_BAD_CHECKSUM) { + status = + acpi_ut_check_text_mode_corruption((u8 *) + *table, + file_size, + (*table)-> + length); + return (status); + } + } + return (AE_OK); + } + + if (actual > 0) { + acpi_os_printf("Warning - reading table, asked for %X got %X\n", + file_size, actual); + return (AE_OK); + } + + acpi_os_printf("Error - could not read the table file\n"); + acpi_os_free(*table); + *table = NULL; + *table_length = 0; + return (AE_ERROR); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_read_table_from_file + * + * PARAMETERS: filename - File where table is located + * table - Where a pointer to the table is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table from a file + * + ******************************************************************************/ + +acpi_status +acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) +{ + FILE *file; + u32 file_size; + u32 table_length; + acpi_status status = AE_ERROR; + + /* Open the file, get current size */ + + file = fopen(filename, "rb"); + if (!file) { + perror("Could not open input file"); + return (status); + } + + file_size = cm_get_file_size(file); + if (file_size == ACPI_UINT32_MAX) { + goto exit; + } + + /* Get the entire file */ + + fprintf(stderr, + "Loading Acpi table from file %10s - Length %.8u (%06X)\n", + filename, file_size, file_size); + + status = acpi_ut_read_table(file, table, &table_length); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not get table from the file\n"); + } + +exit: + fclose(file); + return (status); +} + +#endif diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d69be3cb3fae..77ceac715f28 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -214,152 +214,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = }; #endif /* !ACPI_REDUCED_HARDWARE */ -/******************************************************************************* - * - * FUNCTION: acpi_ut_init_globals - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize ACPICA globals. All globals that require specific - * initialization should be initialized here. This allows for - * a warm restart. - * - ******************************************************************************/ - -acpi_status acpi_ut_init_globals(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ut_init_globals); - - /* Create all memory caches */ - - status = acpi_ut_create_caches(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Address Range lists */ - - for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { - acpi_gbl_address_range_list[i] = NULL; - } - - /* Mutex locked flags */ - - for (i = 0; i < ACPI_NUM_MUTEX; i++) { - acpi_gbl_mutex_info[i].mutex = NULL; - acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_mutex_info[i].use_count = 0; - } - - for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { - acpi_gbl_owner_id_mask[i] = 0; - } - - /* Last owner_ID is never valid */ - - acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; - - /* Event counters */ - - acpi_method_count = 0; - acpi_sci_count = 0; - acpi_gpe_count = 0; - - for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - acpi_fixed_event_count[i] = 0; - } - -#if (!ACPI_REDUCED_HARDWARE) - - /* GPE/SCI support */ - - acpi_gbl_all_gpes_initialized = FALSE; - acpi_gbl_gpe_xrupt_list_head = NULL; - acpi_gbl_gpe_fadt_blocks[0] = NULL; - acpi_gbl_gpe_fadt_blocks[1] = NULL; - acpi_current_gpe_count = 0; - - acpi_gbl_global_event_handler = NULL; - acpi_gbl_sci_handler_list = NULL; - -#endif /* !ACPI_REDUCED_HARDWARE */ - - /* Global handlers */ - - acpi_gbl_global_notify[0].handler = NULL; - acpi_gbl_global_notify[1].handler = NULL; - acpi_gbl_exception_handler = NULL; - acpi_gbl_init_handler = NULL; - acpi_gbl_table_handler = NULL; - acpi_gbl_interface_handler = NULL; - - /* Global Lock support */ - - acpi_gbl_global_lock_semaphore = NULL; - acpi_gbl_global_lock_mutex = NULL; - acpi_gbl_global_lock_acquired = FALSE; - acpi_gbl_global_lock_handle = 0; - acpi_gbl_global_lock_present = FALSE; - - /* Miscellaneous variables */ - - acpi_gbl_DSDT = NULL; - acpi_gbl_cm_single_step = FALSE; - acpi_gbl_shutdown = FALSE; - acpi_gbl_ns_lookup_count = 0; - acpi_gbl_ps_find_count = 0; - acpi_gbl_acpi_hardware_present = TRUE; - acpi_gbl_last_owner_id_index = 0; - acpi_gbl_next_owner_id_offset = 0; - acpi_gbl_trace_dbg_level = 0; - acpi_gbl_trace_dbg_layer = 0; - acpi_gbl_debugger_configuration = DEBUGGER_THREADING; - acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; - acpi_gbl_osi_mutex = NULL; - acpi_gbl_reg_methods_executed = FALSE; - - /* Hardware oriented */ - - acpi_gbl_events_initialized = FALSE; - acpi_gbl_system_awake_and_running = TRUE; - - /* Namespace */ - - acpi_gbl_module_code_list = NULL; - acpi_gbl_root_node = NULL; - acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; - acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; - acpi_gbl_root_node_struct.parent = NULL; - acpi_gbl_root_node_struct.child = NULL; - acpi_gbl_root_node_struct.peer = NULL; - acpi_gbl_root_node_struct.object = NULL; - -#ifdef ACPI_DISASSEMBLER - acpi_gbl_external_list = NULL; - acpi_gbl_num_external_methods = 0; - acpi_gbl_resolved_external_methods = 0; -#endif - -#ifdef ACPI_DEBUG_OUTPUT - acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); -#endif - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_gbl_display_final_mem_stats = FALSE; - acpi_gbl_disable_mem_tracking = FALSE; -#endif - - ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); - - return_ACPI_STATUS(AE_OK); -} - /* Public globals */ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c new file mode 100644 index 000000000000..9afa9441b183 --- /dev/null +++ b/drivers/acpi/acpica/uthex.c @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * Module Name: uthex -- Hex/ASCII support functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_COMPILER +ACPI_MODULE_NAME("uthex") + +/* Hex to ASCII conversion table */ +static char acpi_gbl_hex_to_ascii[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F' +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_hex_to_ascii_char + * + * PARAMETERS: integer - Contains the hex digit + * position - bit position of the digit within the + * integer (multiple of 4) + * + * RETURN: The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) +{ + + return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_hex_char_to_value + * + * PARAMETERS: ascii_char - Hex character in Ascii + * + * RETURN: The binary value of the ascii/hex character + * + * DESCRIPTION: Perform ascii-to-hex translation + * + ******************************************************************************/ + +u8 acpi_ut_ascii_char_to_hex(int hex_char) +{ + + if (hex_char <= 0x39) { + return ((u8)(hex_char - 0x30)); + } + + if (hex_char <= 0x46) { + return ((u8)(hex_char - 0x37)); + } + + return ((u8)(hex_char - 0x57)); +} diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 5f56fc49021e..77120ec9ea86 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -102,6 +102,151 @@ static void acpi_ut_free_gpe_lists(void) } #endif /* !ACPI_REDUCED_HARDWARE */ +/******************************************************************************* + * + * FUNCTION: acpi_ut_init_globals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize ACPICA globals. All globals that require specific + * initialization should be initialized here. This allows for + * a warm restart. + * + ******************************************************************************/ + +acpi_status acpi_ut_init_globals(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ut_init_globals); + + /* Create all memory caches */ + + status = acpi_ut_create_caches(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Address Range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { + acpi_gbl_address_range_list[i] = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + acpi_gbl_mutex_info[i].mutex = NULL; + acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].use_count = 0; + } + + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { + acpi_gbl_owner_id_mask[i] = 0; + } + + /* Last owner_ID is never valid */ + + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + + /* Event counters */ + + acpi_method_count = 0; + acpi_sci_count = 0; + acpi_gpe_count = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_fixed_event_count[i] = 0; + } + +#if (!ACPI_REDUCED_HARDWARE) + + /* GPE/SCI support */ + + acpi_gbl_all_gpes_initialized = FALSE; + acpi_gbl_gpe_xrupt_list_head = NULL; + acpi_gbl_gpe_fadt_blocks[0] = NULL; + acpi_gbl_gpe_fadt_blocks[1] = NULL; + acpi_current_gpe_count = 0; + + acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Global handlers */ + + acpi_gbl_global_notify[0].handler = NULL; + acpi_gbl_global_notify[1].handler = NULL; + acpi_gbl_exception_handler = NULL; + acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; + acpi_gbl_interface_handler = NULL; + + /* Global Lock support */ + + acpi_gbl_global_lock_semaphore = NULL; + acpi_gbl_global_lock_mutex = NULL; + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_handle = 0; + acpi_gbl_global_lock_present = FALSE; + + /* Miscellaneous variables */ + + acpi_gbl_DSDT = NULL; + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + acpi_gbl_acpi_hardware_present = TRUE; + acpi_gbl_last_owner_id_index = 0; + acpi_gbl_next_owner_id_offset = 0; + acpi_gbl_trace_dbg_level = 0; + acpi_gbl_trace_dbg_layer = 0; + acpi_gbl_debugger_configuration = DEBUGGER_THREADING; + acpi_gbl_osi_mutex = NULL; + acpi_gbl_reg_methods_executed = FALSE; + + /* Hardware oriented */ + + acpi_gbl_events_initialized = FALSE; + acpi_gbl_system_awake_and_running = TRUE; + + /* Namespace */ + + acpi_gbl_module_code_list = NULL; + acpi_gbl_root_node = NULL; + acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; + acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; + acpi_gbl_root_node_struct.parent = NULL; + acpi_gbl_root_node_struct.child = NULL; + acpi_gbl_root_node_struct.peer = NULL; + acpi_gbl_root_node_struct.object = NULL; + +#ifdef ACPI_DISASSEMBLER + acpi_gbl_external_list = NULL; + acpi_gbl_num_external_methods = 0; + acpi_gbl_resolved_external_methods = 0; +#endif + +#ifdef ACPI_DEBUG_OUTPUT + acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); +#endif + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_gbl_display_final_mem_stats = FALSE; + acpi_gbl_disable_mem_tracking = FALSE; +#endif + + ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); + + return_ACPI_STATUS(AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_ut_terminate diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c new file mode 100644 index 000000000000..0ce3f5a0dd67 --- /dev/null +++ b/drivers/acpi/acpica/utprint.c @@ -0,0 +1,664 @@ +/****************************************************************************** + * + * Module Name: utprint - Formatted printing routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utprint") + +#define ACPI_FORMAT_SIGN 0x01 +#define ACPI_FORMAT_SIGN_PLUS 0x02 +#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 +#define ACPI_FORMAT_ZERO 0x08 +#define ACPI_FORMAT_LEFT 0x10 +#define ACPI_FORMAT_UPPER 0x20 +#define ACPI_FORMAT_PREFIX 0x40 +/* Local prototypes */ +static acpi_size +acpi_ut_bound_string_length(const char *string, acpi_size count); + +static char *acpi_ut_bound_string_output(char *string, const char *end, char c); + +static char *acpi_ut_format_number(char *string, + char *end, + u64 number, + u8 base, s32 width, s32 precision, u8 type); + +static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper); + +/* Module globals */ + +static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; +static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_bound_string_length + * + * PARAMETERS: string - String with boundary + * count - Boundary of the string + * + * RETURN: Length of the string. Less than or equal to Count. + * + * DESCRIPTION: Calculate the length of a string with boundary. + * + ******************************************************************************/ + +static acpi_size +acpi_ut_bound_string_length(const char *string, acpi_size count) +{ + u32 length = 0; + + while (*string && count) { + length++; + string++; + count--; + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_bound_string_output + * + * PARAMETERS: string - String with boundary + * end - Boundary of the string + * c - Character to be output to the string + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Output a character into a string with boundary check. + * + ******************************************************************************/ + +static char *acpi_ut_bound_string_output(char *string, const char *end, char c) +{ + + if (string < end) { + *string = c; + } + + ++string; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_put_number + * + * PARAMETERS: string - Buffer to hold reverse-ordered string + * number - Integer to be converted + * base - Base of the integer + * upper - Whether or not using upper cased digits + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Convert an integer into a string, note that, the string holds a + * reversed ordered number without the trailing zero. + * + ******************************************************************************/ + +static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper) +{ + const char *digits; + u64 digit_index; + char *pos; + + pos = string; + digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits; + + if (number == 0) { + *(pos++) = '0'; + } else { + while (number) { + (void)acpi_ut_divide(number, base, &number, + &digit_index); + *(pos++) = digits[digit_index]; + } + } + + /* *(Pos++) = '0'; */ + return (pos); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_scan_number + * + * PARAMETERS: string - String buffer + * number_ptr - Where the number is returned + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Scan a string for a decimal integer. + * + ******************************************************************************/ + +const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) +{ + u64 number = 0; + + while (ACPI_IS_DIGIT(*string)) { + number *= 10; + number += *(string++) - '0'; + } + + *number_ptr = number; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_number + * + * PARAMETERS: string - String buffer + * number - The number to be converted + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print a decimal integer into a string. + * + ******************************************************************************/ + +const char *acpi_ut_print_number(char *string, u64 number) +{ + char ascii_string[20]; + const char *pos1; + char *pos2; + + pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE); + pos2 = string; + + while (pos1 != ascii_string) { + *(pos2++) = *(--pos1); + } + + *pos2 = 0; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_format_number + * + * PARAMETERS: string - String buffer with boundary + * end - Boundary of the string + * number - The number to be converted + * base - Base of the integer + * width - Field width + * precision - Precision of the integer + * type - Special printing flags + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print an integer into a string with any base and any precision. + * + ******************************************************************************/ + +static char *acpi_ut_format_number(char *string, + char *end, + u64 number, + u8 base, s32 width, s32 precision, u8 type) +{ + char *pos; + char sign; + char zero; + u8 need_prefix; + u8 upper; + s32 i; + char reversed_string[66]; + + /* Parameter validation */ + + if (base < 2 || base > 16) { + return (NULL); + } + + if (type & ACPI_FORMAT_LEFT) { + type &= ~ACPI_FORMAT_ZERO; + } + + need_prefix = ((type & ACPI_FORMAT_PREFIX) + && base != 10) ? TRUE : FALSE; + upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; + zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; + + /* Calculate size according to sign and prefix */ + + sign = '\0'; + if (type & ACPI_FORMAT_SIGN) { + if ((s64) number < 0) { + sign = '-'; + number = -(s64) number; + width--; + } else if (type & ACPI_FORMAT_SIGN_PLUS) { + sign = '+'; + width--; + } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { + sign = ' '; + width--; + } + } + if (need_prefix) { + width--; + if (base == 16) { + width--; + } + } + + /* Generate full string in reverse order */ + + pos = acpi_ut_put_number(reversed_string, number, base, upper); + i = ACPI_PTR_DIFF(pos, reversed_string); + + /* Printing 100 using %2d gives "100", not "00" */ + + if (i > precision) { + precision = i; + } + + width -= precision; + + /* Output the string */ + + if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) { + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, ' '); + } + } + if (sign) { + string = acpi_ut_bound_string_output(string, end, sign); + } + if (need_prefix) { + string = acpi_ut_bound_string_output(string, end, '0'); + if (base == 16) { + string = acpi_ut_bound_string_output(string, end, + upper ? 'X' : 'x'); + } + } + if (!(type & ACPI_FORMAT_LEFT)) { + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, zero); + } + } + + while (i <= --precision) { + string = acpi_ut_bound_string_output(string, end, '0'); + } + while (--i >= 0) { + string = acpi_ut_bound_string_output(string, end, + reversed_string[i]); + } + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, ' '); + } + + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_vsnprintf + * + * PARAMETERS: string - String with boundary + * size - Boundary of the string + * format - Standard printf format + * args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string using argument list pointer. + * + ******************************************************************************/ + +int +acpi_ut_vsnprintf(char *string, + acpi_size size, const char *format, va_list args) +{ + u8 base = 10; + u8 type = 0; + s32 width = -1; + s32 precision = -1; + char qualifier = 0; + u64 number; + char *pos; + char *end; + char c; + const char *s; + const void *p; + s32 length; + int i; + + pos = string; + end = string + size; + + for (; *format; ++format) { + if (*format != '%') { + pos = acpi_ut_bound_string_output(pos, end, *format); + continue; + } + + /* Process sign */ + + do { + ++format; + if (*format == '#') { + type |= ACPI_FORMAT_PREFIX; + } else if (*format == '0') { + type |= ACPI_FORMAT_ZERO; + } else if (*format == '+') { + type |= ACPI_FORMAT_SIGN_PLUS; + } else if (*format == ' ') { + type |= ACPI_FORMAT_SIGN_PLUS_SPACE; + } else if (*format == '-') { + type |= ACPI_FORMAT_LEFT; + } else { + break; + } + } while (1); + + /* Process width */ + + width = -1; + if (ACPI_IS_DIGIT(*format)) { + format = acpi_ut_scan_number(format, &number); + width = (s32) number; + } else if (*format == '*') { + ++format; + width = va_arg(args, int); + if (width < 0) { + width = -width; + type |= ACPI_FORMAT_LEFT; + } + } + + /* Process precision */ + + precision = -1; + if (*format == '.') { + ++format; + if (ACPI_IS_DIGIT(*format)) { + format = acpi_ut_scan_number(format, &number); + precision = (s32) number; + } else if (*format == '*') { + ++format; + precision = va_arg(args, int); + } + if (precision < 0) { + precision = 0; + } + } + + /* Process qualifier */ + + qualifier = -1; + if (*format == 'h' || *format == 'l' || *format == 'L') { + qualifier = *format; + ++format; + + if (qualifier == 'l' && *format == 'l') { + qualifier = 'L'; + ++format; + } + } + + switch (*format) { + case '%': + + pos = acpi_ut_bound_string_output(pos, end, '%'); + continue; + + case 'c': + + if (!(type & ACPI_FORMAT_LEFT)) { + while (--width > 0) { + pos = + acpi_ut_bound_string_output(pos, + end, + ' '); + } + } + + c = (char)va_arg(args, int); + pos = acpi_ut_bound_string_output(pos, end, c); + + while (--width > 0) { + pos = + acpi_ut_bound_string_output(pos, end, ' '); + } + continue; + + case 's': + + s = va_arg(args, char *); + if (!s) { + s = "<NULL>"; + } + length = acpi_ut_bound_string_length(s, precision); + if (!(type & ACPI_FORMAT_LEFT)) { + while (length < width--) { + pos = + acpi_ut_bound_string_output(pos, + end, + ' '); + } + } + for (i = 0; i < length; ++i) { + pos = acpi_ut_bound_string_output(pos, end, *s); + ++s; + } + while (length < width--) { + pos = + acpi_ut_bound_string_output(pos, end, ' '); + } + continue; + + case 'o': + + base = 8; + break; + + case 'X': + + type |= ACPI_FORMAT_UPPER; + + case 'x': + + base = 16; + break; + + case 'd': + case 'i': + + type |= ACPI_FORMAT_SIGN; + + case 'u': + + break; + + case 'p': + + if (width == -1) { + width = 2 * sizeof(void *); + type |= ACPI_FORMAT_ZERO; + } + + p = va_arg(args, void *); + pos = acpi_ut_format_number(pos, end, + ACPI_TO_INTEGER(p), 16, + width, precision, type); + continue; + + default: + + pos = acpi_ut_bound_string_output(pos, end, '%'); + if (*format) { + pos = + acpi_ut_bound_string_output(pos, end, + *format); + } else { + --format; + } + continue; + } + + if (qualifier == 'L') { + number = va_arg(args, u64); + if (type & ACPI_FORMAT_SIGN) { + number = (s64) number; + } + } else if (qualifier == 'l') { + number = va_arg(args, unsigned long); + if (type & ACPI_FORMAT_SIGN) { + number = (s32) number; + } + } else if (qualifier == 'h') { + number = (u16)va_arg(args, int); + if (type & ACPI_FORMAT_SIGN) { + number = (s16) number; + } + } else { + number = va_arg(args, unsigned int); + if (type & ACPI_FORMAT_SIGN) { + number = (signed int)number; + } + } + + pos = acpi_ut_format_number(pos, end, number, base, + width, precision, type); + } + + if (size > 0) { + if (pos < end) { + *pos = '\0'; + } else { + end[-1] = '\0'; + } + } + + return (ACPI_PTR_DIFF(pos, string)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_snprintf + * + * PARAMETERS: string - String with boundary + * size - Boundary of the string + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string. + * + ******************************************************************************/ + +int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) +{ + va_list args; + int length; + + va_start(args, format); + length = acpi_ut_vsnprintf(string, size, format, args); + va_end(args); + + return (length); +} + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_ut_file_vprintf + * + * PARAMETERS: file - File descriptor + * format - Standard printf format + * args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file using argument list pointer. + * + ******************************************************************************/ + +int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) +{ + acpi_cpu_flags flags; + int length; + + flags = acpi_os_acquire_lock(acpi_gbl_print_lock); + length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, + sizeof(acpi_gbl_print_buffer), format, args); + + (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); + acpi_os_release_lock(acpi_gbl_print_lock, flags); + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_file_printf + * + * PARAMETERS: file - File descriptor + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file. + * + ******************************************************************************/ + +int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) +{ + va_list args; + int length; + + va_start(args, format); + length = acpi_ut_file_vprintf(file, format, args); + va_end(args); + + return (length); +} +#endif diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c new file mode 100644 index 000000000000..4dc33130f134 --- /dev/null +++ b/drivers/acpi/acpica/utuuid.c @@ -0,0 +1,96 @@ +/****************************************************************************** + * + * Module Name: utuuid -- UUID support functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_COMPILER +ACPI_MODULE_NAME("utuuid") + +/* + * UUID support functions. + * + * This table is used to convert an input UUID ascii string to a 16 byte + * buffer and the reverse. The table maps a UUID buffer index 0-15 to + * the index within the 36-byte UUID string where the associated 2-byte + * hex value can be found. + * + * 36-byte UUID strings are of the form: + * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + * Where aa-pp are one byte hex numbers, made up of two hex digits + * + * Note: This table is basically the inverse of the string-to-offset table + * found in the ACPI spec in the description of the to_UUID macro. + */ +const u8 acpi_gbl_map_to_uuid_offset[UUID_BUFFER_LENGTH] = { + 6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34 +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_string_to_uuid + * + * PARAMETERS: in_string - 36-byte formatted UUID string + * uuid_buffer - Where the 16-byte UUID buffer is returned + * + * RETURN: None. Output data is returned in the uuid_buffer + * + * DESCRIPTION: Convert a 36-byte formatted UUID string to 16-byte UUID buffer + * + ******************************************************************************/ + +void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer) +{ + u32 i; + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) { + uuid_buffer[i] = + (acpi_ut_ascii_char_to_hex + (in_string[acpi_gbl_map_to_uuid_offset[i]]) << 4); + + uuid_buffer[i] |= + acpi_ut_ascii_char_to_hex(in_string + [acpi_gbl_map_to_uuid_offset[i] + + 1]); + } +} diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index e5bcd919d4e6..16129c78b489 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -121,11 +121,11 @@ struct dentry; struct dentry *apei_get_debugfs_dir(void); #define apei_estatus_for_each_section(estatus, section) \ - for (section = (struct acpi_generic_data *)(estatus + 1); \ + for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ (void *)section - (void *)estatus < estatus->data_length; \ section = (void *)(section+1) + section->error_data_length) -static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) +static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus) { if (estatus->raw_data_length) return estatus->raw_data_offset + \ @@ -135,9 +135,9 @@ static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) } void cper_estatus_print(const char *pfx, - const struct acpi_generic_status *estatus); -int cper_estatus_check_header(const struct acpi_generic_status *estatus); -int cper_estatus_check(const struct acpi_generic_status *estatus); + const struct acpi_hest_generic_status *estatus); +int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus); +int cper_estatus_check(const struct acpi_hest_generic_status *estatus); int apei_osc_setup(void); #endif diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index e05d84e7b06d..fc5f780bb61d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -74,13 +74,13 @@ #define GHES_ESTATUS_CACHE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_cache) + (estatus_len)) #define GHES_ESTATUS_FROM_CACHE(estatus_cache) \ - ((struct acpi_generic_status *) \ + ((struct acpi_hest_generic_status *) \ ((struct ghes_estatus_cache *)(estatus_cache) + 1)) #define GHES_ESTATUS_NODE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_node) + (estatus_len)) #define GHES_ESTATUS_FROM_NODE(estatus_node) \ - ((struct acpi_generic_status *) \ + ((struct acpi_hest_generic_status *) \ ((struct ghes_estatus_node *)(estatus_node) + 1)) bool ghes_disable; @@ -388,7 +388,7 @@ static void ghes_clear_estatus(struct ghes *ghes) ghes->flags &= ~GHES_TO_CLEAR; } -static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) +static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) { #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE unsigned long pfn; @@ -421,10 +421,10 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) } static void ghes_do_proc(struct ghes *ghes, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { int sev, sec_sev; - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { @@ -476,7 +476,7 @@ static void ghes_do_proc(struct ghes *ghes, static void __ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { static atomic_t seqno; unsigned int curr_seqno; @@ -498,7 +498,7 @@ static void __ghes_print_estatus(const char *pfx, static int ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { /* Not more than 2 messages every 5 seconds */ static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); @@ -520,13 +520,13 @@ static int ghes_print_estatus(const char *pfx, * GHES error status reporting throttle, to report more kinds of * errors, instead of just most frequently occurred errors. */ -static int ghes_estatus_cached(struct acpi_generic_status *estatus) +static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus) { u32 len; int i, cached = 0; unsigned long long now; struct ghes_estatus_cache *cache; - struct acpi_generic_status *cache_estatus; + struct acpi_hest_generic_status *cache_estatus; len = cper_estatus_len(estatus); rcu_read_lock(); @@ -551,12 +551,12 @@ static int ghes_estatus_cached(struct acpi_generic_status *estatus) static struct ghes_estatus_cache *ghes_estatus_cache_alloc( struct acpi_hest_generic *generic, - struct acpi_generic_status *estatus) + struct acpi_hest_generic_status *estatus) { int alloced; u32 len, cache_len; struct ghes_estatus_cache *cache; - struct acpi_generic_status *cache_estatus; + struct acpi_hest_generic_status *cache_estatus; alloced = atomic_add_return(1, &ghes_estatus_cache_alloced); if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) { @@ -599,7 +599,7 @@ static void ghes_estatus_cache_rcu_free(struct rcu_head *head) static void ghes_estatus_cache_add( struct acpi_hest_generic *generic, - struct acpi_generic_status *estatus) + struct acpi_hest_generic_status *estatus) { int i, slot = -1, count; unsigned long long now, duration, period, max_period = 0; @@ -757,7 +757,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) struct llist_node *llnode, *next; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -790,7 +790,7 @@ static void ghes_print_queued_estatus(void) struct llist_node *llnode; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -849,7 +849,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG u32 len, node_len; struct ghes_estatus_node *estatus_node; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; #endif if (!(ghes->flags & GHES_TO_CLEAR)) continue; @@ -991,7 +991,7 @@ static int ghes_probe(struct platform_device *ghes_dev) rc = -EIO; if (generic->error_block_length < - sizeof(struct acpi_generic_status)) { + sizeof(struct acpi_hest_generic_status)) { pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", generic->error_block_length, generic->header.source_id); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 130f513e08c9..48bcf38a0ea8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -35,7 +35,6 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/suspend.h> -#include <linux/delay.h> #include <asm/unaligned.h> #ifdef CONFIG_ACPI_PROCFS_POWER diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 3d8413d02a97..36eb42e3b0bb 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -247,75 +247,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, /* - * The following machines have broken backlight support when reporting - * the Windows 2012 OSI, so disable it until their support is fixed. + * These machines will power on immediately after shutdown when + * reporting the Windows 2012 OSI. */ { .callback = dmi_disable_osi_win8, - .ident = "ASUS Zenbook Prime UX31A", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Acer Aspire V5-573G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Acer Aspire V5-572G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad T431s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad T430", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), - }, - }, - { - .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 7737", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c5bc8cfe09fa..8581f5b84f48 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -477,9 +477,6 @@ static int __init acpi_bus_init_irq(void) return 0; } -u8 acpi_gbl_permanent_mmap; - - void __init acpi_early_init(void) { acpi_status status; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index db35594d4df7..6d5d1832a588 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP +static int acpi_button_suspend(struct device *dev); static int acpi_button_resume(struct device *dev); #else +#define acpi_button_suspend NULL #define acpi_button_resume NULL #endif -static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); +static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume); static struct acpi_driver acpi_button_driver = { .name = "button", @@ -102,6 +104,7 @@ struct acpi_button { struct input_dev *input; char phys[32]; /* for input device */ unsigned long pushed; + bool suspended; }; static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); @@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) if (button->type == ACPI_BUTTON_TYPE_LID) { acpi_lid_send_state(device); } else { - int keycode = test_bit(KEY_SLEEP, input->keybit) ? - KEY_SLEEP : KEY_POWER; + int keycode; + + pm_wakeup_event(&device->dev, 0); + if (button->suspended) + break; + keycode = test_bit(KEY_SLEEP, input->keybit) ? + KEY_SLEEP : KEY_POWER; input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); input_sync(input); - pm_wakeup_event(&device->dev, 0); acpi_bus_generate_netlink_event( device->pnp.device_class, dev_name(&device->dev), @@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) } #ifdef CONFIG_PM_SLEEP +static int acpi_button_suspend(struct device *dev) +{ + struct acpi_device *device = to_acpi_device(dev); + struct acpi_button *button = acpi_driver_data(device); + + button->suspended = true; + return 0; +} + static int acpi_button_resume(struct device *dev) { struct acpi_device *device = to_acpi_device(dev); struct acpi_button *button = acpi_driver_data(device); + button->suspended = false; if (button->type == ACPI_BUTTON_TYPE_LID) return acpi_lid_send_state(device); return 0; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 49a51277f81d..67075f800e34 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable); #ifdef CONFIG_PM static DEFINE_MUTEX(acpi_pm_notifier_lock); +static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) +{ + struct acpi_device *adev; + + if (val != ACPI_NOTIFY_DEVICE_WAKE) + return; + + adev = acpi_bus_get_acpi_device(handle); + if (!adev) + return; + + mutex_lock(&acpi_pm_notifier_lock); + + if (adev->wakeup.flags.notifier_present) { + __pm_wakeup_event(adev->wakeup.ws, 0); + if (adev->wakeup.context.work.func) + queue_pm_work(&adev->wakeup.context.work); + } + + mutex_unlock(&acpi_pm_notifier_lock); + + acpi_bus_put_acpi_device(adev); +} + /** - * acpi_add_pm_notifier - Register PM notifier for given ACPI device. - * @adev: ACPI device to add the notifier for. - * @context: Context information to pass to the notifier routine. + * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. + * @adev: ACPI device to add the notify handler for. + * @dev: Device to generate a wakeup event for while handling the notification. + * @work_func: Work function to execute when handling the notification. * * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of * PM wakeup events. For example, wakeup events may be generated for bridges * if one of the devices below the bridge is signaling wakeup, even if the * bridge itself doesn't have a wakeup GPE associated with it. */ -acpi_status acpi_add_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler, void *context) +acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, + void (*work_func)(struct work_struct *work)) { acpi_status status = AE_ALREADY_EXISTS; + if (!dev && !work_func) + return AE_BAD_PARAMETER; + mutex_lock(&acpi_pm_notifier_lock); if (adev->wakeup.flags.notifier_present) goto out; - status = acpi_install_notify_handler(adev->handle, - ACPI_SYSTEM_NOTIFY, - handler, context); + adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); + adev->wakeup.context.dev = dev; + if (work_func) + INIT_WORK(&adev->wakeup.context.work, work_func); + + status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, + acpi_pm_notify_handler, NULL); if (ACPI_FAILURE(status)) goto out; @@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. * @adev: ACPI device to remove the notifier from. */ -acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler) +acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) { acpi_status status = AE_BAD_PARAMETER; @@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, status = acpi_remove_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, - handler); + acpi_pm_notify_handler); if (ACPI_FAILURE(status)) goto out; + if (adev->wakeup.context.work.func) { + cancel_work_sync(&adev->wakeup.context.work); + adev->wakeup.context.work.func = NULL; + } + adev->wakeup.context.dev = NULL; + wakeup_source_unregister(adev->wakeup.ws); + adev->wakeup.flags.notifier_present = false; out: @@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, */ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) { - acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *adev; int ret, d_min, d_max; @@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) d_max_in = ACPI_STATE_D3_HOT; } - if (!handle || acpi_bus_get_device(handle, &adev)) { - dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); + adev = ACPI_COMPANION(dev); + if (!adev) { + dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); return -ENODEV; } @@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) } EXPORT_SYMBOL(acpi_pm_device_sleep_state); -#ifdef CONFIG_PM_RUNTIME /** - * acpi_wakeup_device - Wakeup notification handler for ACPI devices. - * @handle: ACPI handle of the device the notification is for. - * @event: Type of the signaled event. - * @context: Device corresponding to @handle. + * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. + * @work: Work item to handle. */ -static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) +static void acpi_pm_notify_work_func(struct work_struct *work) { - struct device *dev = context; + struct device *dev; - if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { + dev = container_of(work, struct acpi_device_wakeup_context, work)->dev; + if (dev) { pm_wakeup_event(dev, 0); pm_runtime_resume(dev); } } /** - * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device. - * @adev: ACPI device to enable/disable the remote wakeup for. + * acpi_device_wakeup - Enable/disable wakeup functionality for device. + * @adev: ACPI device to enable/disable wakeup functionality for. + * @target_state: State the system is transitioning into. * @enable: Whether to enable or disable the wakeup functionality. * * Enable/disable the GPE associated with @adev so that it can generate @@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) * Callers must ensure that @adev is a valid ACPI device node before executing * this function. */ -int __acpi_device_run_wake(struct acpi_device *adev, bool enable) +static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state, + bool enable) { struct acpi_device_wakeup *wakeup = &adev->wakeup; @@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) acpi_status res; int error; - error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0); + error = acpi_enable_wakeup_device_power(adev, target_state); if (error) return error; @@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) return 0; } +#ifdef CONFIG_PM_RUNTIME /** * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. * @dev: Device to enable/disable the platform to wake up. @@ -661,63 +700,42 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) { struct acpi_device *adev; - acpi_handle handle; if (!device_run_wake(phys_dev)) return -EINVAL; - handle = ACPI_HANDLE(phys_dev); - if (!handle || acpi_bus_get_device(handle, &adev)) { - dev_dbg(phys_dev, "ACPI handle without context in %s!\n", - __func__); + adev = ACPI_COMPANION(phys_dev); + if (!adev) { + dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__); return -ENODEV; } - return __acpi_device_run_wake(adev, enable); + return acpi_device_wakeup(adev, enable, ACPI_STATE_S0); } EXPORT_SYMBOL(acpi_pm_device_run_wake); -#else -static inline void acpi_wakeup_device(acpi_handle handle, u32 event, - void *context) {} #endif /* CONFIG_PM_RUNTIME */ #ifdef CONFIG_PM_SLEEP /** - * __acpi_device_sleep_wake - Enable or disable device to wake up the system. - * @dev: Device to enable/desible to wake up the system. - * @target_state: System state the device is supposed to wake up from. - * @enable: Whether to enable or disable @dev to wake up the system. - */ -int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state, - bool enable) -{ - return enable ? - acpi_enable_wakeup_device_power(adev, target_state) : - acpi_disable_wakeup_device_power(adev); -} - -/** * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. * @dev: Device to enable/desible to wake up the system from sleep states. * @enable: Whether to enable or disable @dev to wake up the system. */ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) { - acpi_handle handle; struct acpi_device *adev; int error; if (!device_can_wakeup(dev)) return -EINVAL; - handle = ACPI_HANDLE(dev); - if (!handle || acpi_bus_get_device(handle, &adev)) { - dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); + adev = ACPI_COMPANION(dev); + if (!adev) { + dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); return -ENODEV; } - error = __acpi_device_sleep_wake(adev, acpi_target_system_state(), - enable); + error = acpi_device_wakeup(adev, acpi_target_system_state(), enable); if (!error) dev_info(dev, "System wakeup %s by ACPI\n", enable ? "enabled" : "disabled"); @@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev) remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > PM_QOS_FLAGS_NONE; - error = __acpi_device_run_wake(adev, remote_wakeup); + error = acpi_device_wakeup(adev, ACPI_STATE_S0, remote_wakeup); if (remote_wakeup && error) return -EAGAIN; error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); if (error) - __acpi_device_run_wake(adev, false); + acpi_device_wakeup(adev, ACPI_STATE_S0, false); return error; } @@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev) return 0; error = acpi_dev_pm_full_power(adev); - __acpi_device_run_wake(adev, false); + acpi_device_wakeup(adev, ACPI_STATE_S0, false); return error; } EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); @@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev) target_state = acpi_target_system_state(); wakeup = device_may_wakeup(dev); - error = __acpi_device_sleep_wake(adev, target_state, wakeup); + error = acpi_device_wakeup(adev, target_state, wakeup); if (wakeup && error) return error; error = acpi_dev_pm_low_power(dev, adev, target_state); if (error) - __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); + acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); return error; } @@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev) return 0; error = acpi_dev_pm_full_power(adev); - __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); + acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); return error; } EXPORT_SYMBOL_GPL(acpi_dev_resume_early); @@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) if (dev->pm_domain) return -EEXIST; - acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); + acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { acpi_dev_pm_full_power(adev); - __acpi_device_run_wake(adev, false); + acpi_device_wakeup(adev, ACPI_STATE_S0, false); } return 0; } @@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) if (adev && dev->pm_domain == &acpi_general_pm_domain) { dev->pm_domain = NULL; - acpi_remove_pm_notifier(adev, acpi_wakeup_device); + acpi_remove_pm_notifier(adev); if (power_off) { /* * If the device's PM QoS resume latency limit or flags @@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) */ dev_pm_qos_hide_latency_limit(dev); dev_pm_qos_hide_flags(dev); - __acpi_device_run_wake(adev, false); + acpi_device_wakeup(adev, ACPI_STATE_S0, false); acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); } } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7de5b603f272..4c5cf77e7576 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -84,8 +84,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, int type, unsigned long long sta); void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); -int acpi_bind_one(struct device *dev, 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); @@ -108,7 +106,12 @@ int acpi_power_transition(struct acpi_device *device, int state); int acpi_device_update_power(struct acpi_device *device, int *state_p); int acpi_wakeup_device_init(void); + +#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC void acpi_early_processor_set_pdc(void); +#else +static inline void acpi_early_processor_set_pdc(void) {} +#endif /* -------------------------------------------------------------------------- Embedded Controller diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bad25b070fe0..3abe9b223ba7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -259,12 +259,14 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) "System description tables not found\n"); return 0; } - } else { + } else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) { acpi_physical_address pa = 0; acpi_find_root_pointer(&pa); return pa; } + + return 0; } /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d388f13d48b4..e6ae603ed1a1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (no_aspm) pcie_no_aspm(); - pci_acpi_add_bus_pm_notifier(device, root->bus); + pci_acpi_add_bus_pm_notifier(device); if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 71e2065639a6..e32321ce9a5c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -4,17 +4,11 @@ * * Alex Chiang <achiang@hp.com> * - Unified x86/ia64 implementations - * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> - * - Added _PDC for platforms with Intel CPUs */ #include <linux/export.h> -#include <linux/dmi.h> -#include <linux/slab.h> #include <linux/acpi.h> #include <acpi/processor.h> -#include "internal.h" - #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_core"); @@ -135,6 +129,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_LOCAL_X2APIC) { + map_x2apic_id(header, type, acpi_id, &apic_id); } exit: @@ -208,195 +204,3 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) return acpi_map_cpuid(apic_id, acpi_id); } EXPORT_SYMBOL_GPL(acpi_get_cpuid); - -static bool __init processor_physically_present(acpi_handle handle) -{ - int cpuid, type; - u32 acpi_id; - acpi_status status; - acpi_object_type acpi_type; - unsigned long long tmp; - union acpi_object object = { 0 }; - struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - - status = acpi_get_type(handle, &acpi_type); - if (ACPI_FAILURE(status)) - return false; - - switch (acpi_type) { - case ACPI_TYPE_PROCESSOR: - status = acpi_evaluate_object(handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) - return false; - acpi_id = object.processor.proc_id; - break; - case ACPI_TYPE_DEVICE: - status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); - if (ACPI_FAILURE(status)) - return false; - acpi_id = tmp; - break; - default: - return false; - } - - type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; - cpuid = acpi_get_cpuid(handle, type, acpi_id); - - if (cpuid == -1) - return false; - - return true; -} - -static void acpi_set_pdc_bits(u32 *buf) -{ - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - - /* Enable coordination with firmware's _TSD info */ - buf[2] = ACPI_PDC_SMP_T_SWCOORD; - - /* Twiddle arch-specific bits needed for _PDC */ - arch_acpi_set_pdc_bits(buf); -} - -static struct acpi_object_list *acpi_processor_alloc_pdc(void) -{ - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return NULL; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return NULL; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return NULL; - } - - acpi_set_pdc_bits(buf); - - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - - return obj_list; -} - -/* - * _PDC is required for a BIOS-OS handshake for most of the newer - * ACPI processor features. - */ -static acpi_status -acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) -{ - acpi_status status = AE_OK; - - if (boot_option_idle_override == IDLE_NOMWAIT) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } - status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Could not evaluate _PDC, using legacy perf. control.\n")); - - return status; -} - -void acpi_processor_set_pdc(acpi_handle handle) -{ - struct acpi_object_list *obj_list; - - if (arch_has_acpi_pdc() == false) - return; - - obj_list = acpi_processor_alloc_pdc(); - if (!obj_list) - return; - - acpi_processor_eval_pdc(handle, obj_list); - - kfree(obj_list->pointer->buffer.pointer); - kfree(obj_list->pointer); - kfree(obj_list); -} - -static acpi_status __init -early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - if (processor_physically_present(handle) == false) - return AE_OK; - - acpi_processor_set_pdc(handle); - return AE_OK; -} - -#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(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); -} diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c new file mode 100644 index 000000000000..e5dd80800930 --- /dev/null +++ b/drivers/acpi/processor_pdc.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * - Added _PDC for platforms with Intel CPUs + */ + +#define pr_fmt(fmt) "ACPI: " fmt + +#include <linux/dmi.h> +#include <linux/slab.h> +#include <linux/acpi.h> +#include <acpi/processor.h> + +#include "internal.h" + +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME("processor_pdc"); + +static bool __init processor_physically_present(acpi_handle handle) +{ + int cpuid, type; + u32 acpi_id; + acpi_status status; + acpi_object_type acpi_type; + unsigned long long tmp; + union acpi_object object = { 0 }; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + + status = acpi_get_type(handle, &acpi_type); + if (ACPI_FAILURE(status)) + return false; + + switch (acpi_type) { + case ACPI_TYPE_PROCESSOR: + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + return false; + acpi_id = object.processor.proc_id; + break; + case ACPI_TYPE_DEVICE: + status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + acpi_id = tmp; + break; + default: + return false; + } + + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; + cpuid = acpi_get_cpuid(handle, type, acpi_id); + + if (cpuid == -1) + return false; + + return true; +} + +static void acpi_set_pdc_bits(u32 *buf) +{ + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; + + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); +} + +static struct acpi_object_list *acpi_processor_alloc_pdc(void) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) + goto out; + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + kfree(obj_list); + goto out; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + kfree(obj); + kfree(obj_list); + goto out; + } + + acpi_set_pdc_bits(buf); + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + + return obj_list; +out: + pr_err("Memory allocation error\n"); + return NULL; +} + +/* + * _PDC is required for a BIOS-OS handshake for most of the newer + * ACPI processor features. + */ +static acpi_status +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) +{ + acpi_status status = AE_OK; + + if (boot_option_idle_override == IDLE_NOMWAIT) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; + + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); + + } + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control.\n")); + + return status; +} + +void acpi_processor_set_pdc(acpi_handle handle) +{ + struct acpi_object_list *obj_list; + + if (arch_has_acpi_pdc() == false) + return; + + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; + + acpi_processor_eval_pdc(handle, obj_list); + + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); +} + +static acpi_status __init +early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + if (processor_physically_present(handle) == false) + return AE_OK; + + acpi_processor_set_pdc(handle); + return AE_OK; +} + +static int __init set_no_mwait(const struct dmi_system_id *id) +{ + pr_notice("%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); +} + +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(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f775fa0d850f..5d592e17d760 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -77,7 +77,9 @@ void acpi_initialize_hp_context(struct acpi_device *adev, void (*uevent)(struct acpi_device *, u32)) { acpi_lock_hp_context(); - acpi_set_hp_context(adev, hp, notify, uevent, NULL); + hp->notify = notify; + hp->uevent = uevent; + acpi_set_hp_context(adev, hp); acpi_unlock_hp_context(); } EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); @@ -1421,14 +1423,13 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, wakeup->sleep_state = sleep_state; } } - acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); out: kfree(buffer.pointer); return err; } -static void acpi_bus_set_run_wake_flags(struct acpi_device *device) +static void acpi_wakeup_gpe_init(struct acpi_device *device) { struct acpi_device_id button_device_ids[] = { {"PNP0C0C", 0}, @@ -1436,29 +1437,33 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) {"PNP0C0E", 0}, {"", 0}, }; + struct acpi_device_wakeup *wakeup = &device->wakeup; acpi_status status; acpi_event_status event_status; - device->wakeup.flags.notifier_present = 0; + wakeup->flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) { - device->wakeup.flags.run_wake = 1; + wakeup->flags.run_wake = 1; if (!acpi_match_device_ids(device, &button_device_ids[1])) { /* Do not use Lid/sleep button for S5 wakeup */ - if (device->wakeup.sleep_state == ACPI_STATE_S5) - device->wakeup.sleep_state = ACPI_STATE_S4; + if (wakeup->sleep_state == ACPI_STATE_S5) + wakeup->sleep_state = ACPI_STATE_S4; } + acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); device_set_wakeup_capable(&device->dev, true); return; } - status = acpi_get_gpe_status(device->wakeup.gpe_device, - device->wakeup.gpe_number, - &event_status); - if (status == AE_OK) - device->wakeup.flags.run_wake = - !!(event_status & ACPI_EVENT_FLAG_HANDLE); + acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device, + wakeup->gpe_number); + status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number, + &event_status); + if (ACPI_FAILURE(status)) + return; + + wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE); } static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) @@ -1478,7 +1483,7 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) device->wakeup.flags.valid = 1; device->wakeup.prepare_count = 0; - acpi_bus_set_run_wake_flags(device); + acpi_wakeup_gpe_init(device); /* Call _PSW/_DSW object to disable its ability to wake the sleeping * system for the ACPI device with the _PRW object. * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index b3e3cc73ba79..54da4a3fe65e 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = { static void acpi_sleep_dmi_check(void) { + int year; + + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012) + acpi_nvs_nosave_s3(); + dmi_check_system(acpisleep_dmi_table); } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 350d52a8f781..826884392e6b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -204,6 +204,8 @@ struct acpi_video_device { struct acpi_video_device_flags flags; struct acpi_video_device_cap cap; struct list_head entry; + struct delayed_work switch_brightness_work; + int switch_brightness_event; struct acpi_video_bus *video; struct acpi_device *dev; struct acpi_video_device_brightness *brightness; @@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current( unsigned long long *level, bool raw); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); -static int acpi_video_switch_brightness(struct acpi_video_device *device, - int event); +static void acpi_video_switch_brightness(struct work_struct *work); static bool acpi_video_use_native_backlight(void) { @@ -275,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) int request_level = bd->props.brightness + 2; struct acpi_video_device *vd = bl_get_data(bd); + cancel_delayed_work(&vd->switch_brightness_work); return acpi_video_device_lcd_set_level(vd, vd->brightness->levels[request_level]); } @@ -461,6 +463,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, + .ident = "ThinkPad X230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, + { + .callback = video_set_use_native_backlight, .ident = "ThinkPad T430 and T430s", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -469,10 +479,42 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, - .ident = "ThinkPad X230", + .ident = "ThinkPad T430", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T431s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), }, }, { @@ -572,6 +614,30 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, }, { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-572G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-573G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ASUS Zenbook Prime UX31A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), + }, + }, + { .callback = video_set_use_native_backlight, .ident = "HP ProBook 4340s", .matches = { @@ -607,6 +673,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 2014 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G2"), + }, + }, + { + .callback = video_set_use_native_backlight, .ident = "HP ZBook 14", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -1188,6 +1263,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, data->device_id = device_id; data->video = video; data->dev = device; + INIT_DELAYED_WORK(&data->switch_brightness_work, + acpi_video_switch_brightness); attribute = acpi_video_get_device_attr(video, device_id); @@ -1410,15 +1487,18 @@ acpi_video_get_next_level(struct acpi_video_device *device, } } -static int -acpi_video_switch_brightness(struct acpi_video_device *device, int event) +static void +acpi_video_switch_brightness(struct work_struct *work) { + struct acpi_video_device *device = container_of(to_delayed_work(work), + struct acpi_video_device, switch_brightness_work); unsigned long long level_current, level_next; + int event = device->switch_brightness_event; int result = -EINVAL; /* no warning message if acpi_backlight=vendor or a quirk is used */ if (!acpi_video_verify_backlight_support()) - return 0; + return; if (!device->brightness) goto out; @@ -1440,8 +1520,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) out: if (result) printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); - - return result; } int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, @@ -1609,6 +1687,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) return; } +static void brightness_switch_event(struct acpi_video_device *video_device, + u32 event) +{ + if (!brightness_switch_enabled) + return; + + video_device->switch_brightness_event = event; + schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10); +} + static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_video_device *video_device = data; @@ -1626,28 +1714,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_DISPLAY_OFF; break; default: diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bf412961a934..b67d9aef9fe4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -465,6 +465,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd) * device_resume_noirq - Execute an "early resume" callback for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. + * @async: If true, the device is being resumed asynchronously. * * The driver of @dev will not receive interrupts while this function is being * executed. @@ -594,6 +595,7 @@ static void dpm_resume_noirq(pm_message_t state) * device_resume_early - Execute an "early resume" callback for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. + * @async: If true, the device is being resumed asynchronously. * * Runtime PM is disabled for @dev while this function is being executed. */ @@ -1004,6 +1006,7 @@ static pm_message_t resume_event(pm_message_t sleep_state) * device_suspend_noirq - Execute a "late suspend" callback for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. + * @async: If true, the device is being suspended asynchronously. * * The driver of @dev will not receive interrupts while this function is being * executed. @@ -1144,6 +1147,7 @@ static int dpm_suspend_noirq(pm_message_t state) * device_suspend_late - Execute a "late suspend" callback for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. + * @async: If true, the device is being suspended asynchronously. * * Runtime PM is disabled for @dev while this function is being executed. */ @@ -1298,6 +1302,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end); * @dev: Device to suspend. * @state: PM transition of the system being carried out. * @cb: Suspend callback to execute. + * @info: string description of caller. */ static int legacy_suspend(struct device *dev, pm_message_t state, int (*cb)(struct device *dev, pm_message_t state), diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6f024852c6fb..d9fdeddcef96 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) kfree(policy); } -static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) +static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu, + struct device *cpu_dev) { + int ret; + if (WARN_ON(cpu == policy->cpu)) - return; + return 0; + + /* Move kobject to the new policy->cpu */ + ret = kobject_move(&policy->kobj, &cpu_dev->kobj); + if (ret) { + pr_err("%s: Failed to move kobj: %d\n", __func__, ret); + return ret; + } down_write(&policy->rwsem); @@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_UPDATE_POLICY_CPU, policy); + + return 0; } static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) @@ -1153,12 +1165,10 @@ 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 (recover_policy && cpu != policy->cpu) { - update_policy_cpu(policy, cpu); - WARN_ON(kobject_move(&policy->kobj, &dev->kobj)); - } else { + if (recover_policy && cpu != policy->cpu) + WARN_ON(update_policy_cpu(policy, cpu, dev)); + else policy->cpu = cpu; - } cpumask_copy(policy->cpus, cpumask_of(cpu)); @@ -1309,38 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) return __cpufreq_add_dev(dev, sif); } -static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, - unsigned int old_cpu) -{ - struct device *cpu_dev; - int ret; - - /* first sibling now owns the new sysfs dir */ - cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu)); - - 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\n", __func__, ret); - - down_write(&policy->rwsem); - cpumask_set_cpu(old_cpu, policy->cpus); - up_write(&policy->rwsem); - - ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, - "cpufreq"); - - return -EINVAL; - } - - return cpu_dev->id; -} - static int __cpufreq_remove_dev_prepare(struct device *dev, struct subsys_interface *sif) { unsigned int cpu = dev->id, cpus; - int new_cpu, ret; + int ret; unsigned long flags; struct cpufreq_policy *policy; @@ -1380,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, if (cpu != policy->cpu) { sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { - new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); - if (new_cpu >= 0) { - update_policy_cpu(policy, new_cpu); + /* Nominate new CPU */ + int new_cpu = cpumask_any_but(policy->cpus, cpu); + struct device *cpu_dev = get_cpu_device(new_cpu); - if (!cpufreq_suspended) - pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", - __func__, new_cpu, cpu); + sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); + ret = update_policy_cpu(policy, new_cpu, cpu_dev); + if (ret) { + if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj, + "cpufreq")) + pr_err("%s: Failed to restore kobj link to cpu:%d\n", + __func__, cpu_dev->id); + return ret; } + + if (!cpufreq_suspended) + pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", + __func__, new_cpu, cpu); } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) { cpufreq_driver->stop_cpu(policy); } diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 18d409189092..ad3f38fd3eb9 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -170,21 +170,24 @@ static void od_check_cpu(int cpu, unsigned int load) dbs_freq_increase(policy, policy->max); } else { /* Calculate the next frequency proportional to load */ - unsigned int freq_next; - freq_next = load * policy->cpuinfo.max_freq / 100; + unsigned int freq_next, min_f, max_f; + + min_f = policy->cpuinfo.min_freq; + max_f = policy->cpuinfo.max_freq; + freq_next = min_f + load * (max_f - min_f) / 100; /* No longer fully busy, reset rate_mult */ dbs_info->rate_mult = 1; if (!od_tuners->powersave_bias) { __cpufreq_driver_target(policy, freq_next, - CPUFREQ_RELATION_L); + CPUFREQ_RELATION_C); return; } freq_next = od_ops.powersave_bias_target(policy, freq_next, CPUFREQ_RELATION_L); - __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C); } } diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 1632981c4b25..df14766a8e06 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -117,7 +117,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, .frequency = 0, }; struct cpufreq_frequency_table *pos; - unsigned int freq, i = 0; + unsigned int freq, diff, i = 0; pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu); @@ -127,6 +127,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, suboptimal.frequency = ~0; break; case CPUFREQ_RELATION_L: + case CPUFREQ_RELATION_C: optimal.frequency = ~0; break; } @@ -168,6 +169,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, } } break; + case CPUFREQ_RELATION_C: + diff = abs(freq - target_freq); + if (diff < optimal.frequency || + (diff == optimal.frequency && + freq > table[optimal.driver_data].frequency)) { + optimal.frequency = diff; + optimal.driver_data = i; + } + break; } } if (optimal.driver_data > i) { diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index af366c21d4b4..c2d30765bf3d 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -66,10 +66,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) /* scaling up? scale voltage before frequency */ if (new_freq > old_freq) { - ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); - if (ret) { - dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); - return ret; + if (!IS_ERR(pu_reg)) { + ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); + if (ret) { + dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); + return ret; + } } ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); if (ret) { @@ -121,10 +123,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); ret = 0; } - ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); - if (ret) { - dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); - ret = 0; + if (!IS_ERR(pu_reg)) { + ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); + if (ret) { + dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); + ret = 0; + } } } @@ -182,9 +186,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) } arm_reg = regulator_get(cpu_dev, "arm"); - pu_reg = regulator_get(cpu_dev, "pu"); + pu_reg = regulator_get_optional(cpu_dev, "pu"); soc_reg = regulator_get(cpu_dev, "soc"); - if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) { + if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) { dev_err(cpu_dev, "failed to get regulators\n"); ret = -ENOENT; goto put_reg; @@ -268,9 +272,11 @@ soc_opp_out: ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); if (ret > 0) transition_latency += ret * 1000; - ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); - if (ret > 0) - transition_latency += ret * 1000; + if (!IS_ERR(pu_reg)) { + ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); + if (ret > 0) + transition_latency += ret * 1000; + } /* * OPP is maintained in order of increasing frequency, and @@ -327,7 +333,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev) cpufreq_unregister_driver(&imx6q_cpufreq_driver); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); regulator_put(arm_reg); - regulator_put(pu_reg); + if (!IS_ERR(pu_reg)) + regulator_put(pu_reg); regulator_put(soc_reg); clk_put(arm_clk); clk_put(pll1_sys_clk); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 86631cb6f7de..c5eac949760d 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -37,7 +37,6 @@ #define BYT_TURBO_RATIOS 0x66c #define BYT_TURBO_VIDS 0x66d - #define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define fp_toint(X) ((X) >> FRAC_BITS) @@ -50,7 +49,7 @@ static inline int32_t mul_fp(int32_t x, int32_t y) static inline int32_t div_fp(int32_t x, int32_t y) { - return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); + return div_s64((int64_t)x << FRAC_BITS, y); } struct sample { @@ -148,7 +147,7 @@ static struct perf_limits limits = { }; static inline void pid_reset(struct _pid *pid, int setpoint, int busy, - int deadband, int integral) { + int deadband, int integral) { pid->setpoint = setpoint; pid->deadband = deadband; pid->integral = int_tofp(integral); @@ -167,7 +166,6 @@ static inline void pid_i_gain_set(struct _pid *pid, int percent) static inline void pid_d_gain_set(struct _pid *pid, int percent) { - pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); } @@ -207,16 +205,13 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu) pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct); pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct); - pid_reset(&cpu->pid, - pid_params.setpoint, - 100, - pid_params.deadband, - 0); + pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0); } static inline void intel_pstate_reset_all_pid(void) { unsigned int cpu; + for_each_online_cpu(cpu) { if (all_cpu_data[cpu]) intel_pstate_busy_pid_reset(all_cpu_data[cpu]); @@ -230,13 +225,13 @@ static int pid_param_set(void *data, u64 val) intel_pstate_reset_all_pid(); return 0; } + static int pid_param_get(void *data, u64 *val) { *val = *(u32 *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, - pid_param_set, "%llu\n"); +DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n"); struct pid_param { char *name; @@ -253,9 +248,9 @@ static struct pid_param pid_files[] = { {NULL, NULL} }; -static struct dentry *debugfs_parent; -static void intel_pstate_debug_expose_params(void) +static void __init intel_pstate_debug_expose_params(void) { + struct dentry *debugfs_parent; int i = 0; debugfs_parent = debugfs_create_dir("pstate_snb", NULL); @@ -263,8 +258,8 @@ static void intel_pstate_debug_expose_params(void) return; while (pid_files[i].name) { debugfs_create_file(pid_files[i].name, 0660, - debugfs_parent, pid_files[i].value, - &fops_pid_param); + debugfs_parent, pid_files[i].value, + &fops_pid_param); i++; } } @@ -280,10 +275,11 @@ static void intel_pstate_debug_expose_params(void) } static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { unsigned int input; int ret; + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; @@ -296,10 +292,11 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, } static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { unsigned int input; int ret; + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; @@ -307,14 +304,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, limits.max_sysfs_pct = clamp_t(int, input, 0 , 100); limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); + return count; } static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { unsigned int input; int ret; + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; @@ -342,17 +341,16 @@ static struct attribute *intel_pstate_attributes[] = { static struct attribute_group intel_pstate_attr_group = { .attrs = intel_pstate_attributes, }; -static struct kobject *intel_pstate_kobject; -static void intel_pstate_sysfs_expose_params(void) +static void __init intel_pstate_sysfs_expose_params(void) { + struct kobject *intel_pstate_kobject; int rc; intel_pstate_kobject = kobject_create_and_add("intel_pstate", &cpu_subsys.dev_root->kobj); BUG_ON(!intel_pstate_kobject); - rc = sysfs_create_group(intel_pstate_kobject, - &intel_pstate_attr_group); + rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group); BUG_ON(rc); } @@ -360,6 +358,7 @@ static void intel_pstate_sysfs_expose_params(void) static int byt_get_min_pstate(void) { u64 value; + rdmsrl(BYT_RATIOS, value); return (value >> 8) & 0x7F; } @@ -367,6 +366,7 @@ static int byt_get_min_pstate(void) static int byt_get_max_pstate(void) { u64 value; + rdmsrl(BYT_RATIOS, value); return (value >> 16) & 0x7F; } @@ -374,6 +374,7 @@ static int byt_get_max_pstate(void) static int byt_get_turbo_pstate(void) { u64 value; + rdmsrl(BYT_TURBO_RATIOS, value); return value & 0x7F; } @@ -407,7 +408,6 @@ static void byt_get_vid(struct cpudata *cpudata) { u64 value; - rdmsrl(BYT_VIDS, value); cpudata->vid.min = int_tofp((value >> 8) & 0x7f); cpudata->vid.max = int_tofp((value >> 16) & 0x7f); @@ -420,10 +420,10 @@ static void byt_get_vid(struct cpudata *cpudata) cpudata->vid.turbo = value & 0x7f; } - static int core_get_min_pstate(void) { u64 value; + rdmsrl(MSR_PLATFORM_INFO, value); return (value >> 40) & 0xFF; } @@ -431,6 +431,7 @@ static int core_get_min_pstate(void) static int core_get_max_pstate(void) { u64 value; + rdmsrl(MSR_PLATFORM_INFO, value); return (value >> 8) & 0xFF; } @@ -439,9 +440,10 @@ static int core_get_turbo_pstate(void) { u64 value; int nont, ret; + rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); nont = core_get_max_pstate(); - ret = ((value) & 255); + ret = (value) & 255; if (ret <= nont) ret = nont; return ret; @@ -493,12 +495,12 @@ static struct cpu_defaults byt_params = { }, }; - static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) { int max_perf = cpu->pstate.turbo_pstate; int max_perf_adj; int min_perf; + if (limits.no_turbo) max_perf = cpu->pstate.max_pstate; @@ -507,8 +509,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf)); - *min = clamp_t(int, min_perf, - cpu->pstate.min_pstate, max_perf); + *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); } static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) @@ -529,21 +530,6 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) pstate_funcs.set(cpu, pstate); } -static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) -{ - int target; - target = cpu->pstate.current_pstate + steps; - - intel_pstate_set_pstate(cpu, target); -} - -static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps) -{ - int target; - target = cpu->pstate.current_pstate - steps; - intel_pstate_set_pstate(cpu, target); -} - static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { cpu->pstate.min_pstate = pstate_funcs.get_min(); @@ -559,13 +545,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu) { struct sample *sample = &cpu->sample; int64_t core_pct; - int32_t rem; core_pct = int_tofp(sample->aperf) * int_tofp(100); - core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem); - - if ((rem << 1) >= int_tofp(sample->mperf)) - core_pct += 1; + core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); sample->freq = fp_toint( mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); @@ -576,12 +558,12 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu) static inline void intel_pstate_sample(struct cpudata *cpu) { u64 aperf, mperf; + unsigned long flags; + local_irq_save(flags); rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_MPERF, mperf); - - aperf = aperf >> FRAC_BITS; - mperf = mperf >> FRAC_BITS; + local_irq_restore(flags); cpu->last_sample_time = cpu->sample.time; cpu->sample.time = ktime_get(); @@ -598,10 +580,9 @@ static inline void intel_pstate_sample(struct cpudata *cpu) static inline void intel_pstate_set_sample_time(struct cpudata *cpu) { - int sample_time, delay; + int delay; - sample_time = pid_params.sample_rate_ms; - delay = msecs_to_jiffies(sample_time); + delay = msecs_to_jiffies(pid_params.sample_rate_ms); mod_timer_pinned(&cpu->timer, jiffies + delay); } @@ -616,12 +597,12 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) current_pstate = int_tofp(cpu->pstate.current_pstate); core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); - sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC); + sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC; duration_us = (u32) ktime_us_delta(cpu->sample.time, - cpu->last_sample_time); + cpu->last_sample_time); if (duration_us > sample_time * 3) { sample_ratio = div_fp(int_tofp(sample_time), - int_tofp(duration_us)); + int_tofp(duration_us)); core_busy = mul_fp(core_busy, sample_ratio); } @@ -632,20 +613,15 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) { int32_t busy_scaled; struct _pid *pid; - signed int ctl = 0; - int steps; + signed int ctl; pid = &cpu->pid; busy_scaled = intel_pstate_get_scaled_busy(cpu); ctl = pid_calc(pid, busy_scaled); - steps = abs(ctl); - - if (ctl < 0) - intel_pstate_pstate_increase(cpu, steps); - else - intel_pstate_pstate_decrease(cpu, steps); + /* Negative values of ctl increase the pstate and vice versa */ + intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl); } static void intel_pstate_timer_func(unsigned long __data) @@ -705,8 +681,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum) init_timer_deferrable(&cpu->timer); cpu->timer.function = intel_pstate_timer_func; - cpu->timer.data = - (unsigned long)cpu; + cpu->timer.data = (unsigned long)cpu; cpu->timer.expires = jiffies + HZ/100; intel_pstate_busy_pid_reset(cpu); intel_pstate_sample(cpu); @@ -751,7 +726,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100); limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); - limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq; + limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100); limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); @@ -763,8 +738,8 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy) { cpufreq_verify_within_cpu_limits(policy); - if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && - (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) + if (policy->policy != CPUFREQ_POLICY_POWERSAVE && + policy->policy != CPUFREQ_POLICY_PERFORMANCE) return -EINVAL; return 0; @@ -797,7 +772,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || - cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { + cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { limits.turbo_disabled = 1; limits.no_turbo = 1; } @@ -839,8 +814,8 @@ static int intel_pstate_msrs_not_valid(void) rdmsrl(MSR_IA32_MPERF, mperf); if (!pstate_funcs.get_max() || - !pstate_funcs.get_min() || - !pstate_funcs.get_turbo()) + !pstate_funcs.get_min() || + !pstate_funcs.get_turbo()) return -ENODEV; rdmsrl(MSR_IA32_APERF, tmp); @@ -922,14 +897,14 @@ static bool intel_pstate_platform_pwr_mgmt_exists(void) struct acpi_table_header hdr; struct hw_vendor_info *v_info; - if (acpi_disabled - || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr))) + if (acpi_disabled || + ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr))) return false; for (v_info = vendor_info; v_info->valid; v_info++) { - if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) - && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) - && intel_pstate_no_acpi_pss()) + if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) && + !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && + intel_pstate_no_acpi_pss()) return true; } diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index c8012bc86910..f91027259c3c 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -55,6 +55,7 @@ static const struct { unsigned freq; unsigned mult; } usual_frequency_table[] = { + { 350000, 35 }, // 100 * 3.5 { 400000, 40 }, // 100 * 4 { 450000, 45 }, // 100 * 4.5 { 475000, 50 }, // 95 * 5 diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 1b96fb91d32c..32748c36c477 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -15,12 +15,7 @@ config CPU_IDLE if CPU_IDLE config CPU_IDLE_MULTIPLE_DRIVERS - bool "Support multiple cpuidle drivers" - default n - help - Allows the cpuidle framework to use different drivers for each CPU. - This is useful if you have a system with different CPU latencies and - states. If unsure say N. + bool config CPU_IDLE_GOV_LADDER bool "Ladder governor (for periodic timer tick)" diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index b6d69e899f5d..a186dec8e5df 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -10,6 +10,7 @@ config ARM_ARMADA_370_XP_CPUIDLE config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" depends on ARCH_VEXPRESS_TC2_PM + depends on MCPM select ARM_CPU_SUSPEND select CPU_IDLE_MULTIPLE_DRIVERS help diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index cb7019977c50..ee9df5e3f5eb 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -119,11 +119,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, ktime_t time_start, time_end; s64 diff; + trace_cpu_idle_rcuidle(index, dev->cpu); time_start = ktime_get(); entered_state = target_state->enter(dev, drv, index); time_end = ktime_get(); + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); if (!cpuidle_state_is_coupled(dev, drv, entered_state)) local_irq_enable(); diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 9634f20e3926..e431d11abf8d 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -182,10 +182,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) static int poll_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - ktime_t t1, t2; - s64 diff; - - t1 = ktime_get(); local_irq_enable(); if (!current_set_polling_and_test()) { while (!need_resched()) @@ -193,13 +189,6 @@ static int poll_idle(struct cpuidle_device *dev, } current_clr_polling(); - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - return index; } diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 9f08e8cce1af..044ee0df5871 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -144,7 +144,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; - for (i = 0; i < drv->state_count; i++) { + for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { state = &drv->states[i]; lstate = &ldev->states[i]; @@ -156,7 +156,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, if (i < drv->state_count - 1) lstate->threshold.promotion_time = state->exit_latency; - if (i > 0) + if (i > CPUIDLE_DRIVER_STATE_START) lstate->threshold.demotion_time = state->exit_latency; } diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c4f80c15a48d..c3732fa74f82 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -35,7 +35,6 @@ #define RESOLUTION 1024 #define DECAY 8 #define MAX_INTERESTING 50000 -#define STDDEV_THRESH 400 /* diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index efe2f175168f..97c5903b4606 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -445,7 +445,7 @@ static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) #define define_one_driver_ro(_name, show) \ static struct cpuidle_driver_attr attr_driver_##_name = \ - __ATTR(_name, 0644, show, NULL) + __ATTR(_name, 0444, show, NULL) struct cpuidle_driver_kobj { struct cpuidle_driver *drv; diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 49e74c1fc639..3dced0a9eae3 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -68,7 +68,6 @@ comment "DEVFREQ Drivers" config ARM_EXYNOS4_BUS_DEVFREQ bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver" depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM - select ARCH_HAS_OPP select DEVFREQ_GOV_SIMPLE_ONDEMAND select PM_OPP help diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 437e6fd47311..5b53d6183b6b 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -344,7 +344,7 @@ static const char * const pcie_port_type_strs[] = { }; static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, - const struct acpi_generic_data *gdata) + const struct acpi_hest_generic_data *gdata) { if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, @@ -380,7 +380,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, } static void cper_estatus_print_section( - const char *pfx, const struct acpi_generic_data *gdata, int sec_no) + const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no) { uuid_le *sec_type = (uuid_le *)gdata->section_type; __u16 severity; @@ -426,9 +426,9 @@ err_section_too_small: } void cper_estatus_print(const char *pfx, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; unsigned int data_len, gedata_len; int sec_no = 0; char newpfx[64]; @@ -441,7 +441,7 @@ void cper_estatus_print(const char *pfx, "and requires no further action"); printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); + gdata = (struct acpi_hest_generic_data *)(estatus + 1); snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; @@ -453,10 +453,10 @@ void cper_estatus_print(const char *pfx, } EXPORT_SYMBOL_GPL(cper_estatus_print); -int cper_estatus_check_header(const struct acpi_generic_status *estatus) +int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus) { if (estatus->data_length && - estatus->data_length < sizeof(struct acpi_generic_data)) + estatus->data_length < sizeof(struct acpi_hest_generic_data)) return -EINVAL; if (estatus->raw_data_length && estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) @@ -466,9 +466,9 @@ int cper_estatus_check_header(const struct acpi_generic_status *estatus) } EXPORT_SYMBOL_GPL(cper_estatus_check_header); -int cper_estatus_check(const struct acpi_generic_status *estatus) +int cper_estatus_check(const struct acpi_hest_generic_status *estatus) { - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; unsigned int data_len, gedata_len; int rc; @@ -476,7 +476,7 @@ int cper_estatus_check(const struct acpi_generic_status *estatus) if (rc) return rc; data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); + gdata = (struct acpi_hest_generic_data *)(estatus + 1); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; if (gedata_len > data_len - sizeof(*gdata)) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 4306885f48b1..60ab474bfff3 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -85,7 +85,7 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt) *cnt = 0; while (start < end) { scope = start; - if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ACPI || + if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_NAMESPACE || scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; @@ -381,7 +381,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header) struct acpi_dmar_andd *andd = (void *)header; /* Check for NUL termination within the designated length */ - if (strnlen(andd->object_name, header->length - 8) == header->length - 8) { + if (strnlen(andd->device_name, header->length - 8) == header->length - 8) { WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, "Your BIOS is broken; ANDD object name is not NUL-terminated\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", @@ -391,7 +391,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header) return -EINVAL; } pr_info("ANDD device: %x name: %s\n", andd->device_number, - andd->object_name); + andd->device_name); return 0; } @@ -449,17 +449,17 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header) (unsigned long long)rmrr->base_address, (unsigned long long)rmrr->end_address); break; - case ACPI_DMAR_TYPE_ATSR: + case ACPI_DMAR_TYPE_ROOT_ATS: atsr = container_of(header, struct acpi_dmar_atsr, header); pr_info("ATSR flags: %#x\n", atsr->flags); break; - case ACPI_DMAR_HARDWARE_AFFINITY: + case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: rhsa = container_of(header, struct acpi_dmar_rhsa, header); pr_info("RHSA base: %#016Lx proximity domain: %#x\n", (unsigned long long)rhsa->base_address, rhsa->proximity_domain); break; - case ACPI_DMAR_TYPE_ANDD: + case ACPI_DMAR_TYPE_NAMESPACE: /* We don't print this here because we need to sanity-check it first. So print it in dmar_parse_one_andd() instead. */ break; @@ -540,15 +540,15 @@ parse_dmar_table(void) case ACPI_DMAR_TYPE_RESERVED_MEMORY: ret = dmar_parse_one_rmrr(entry_header); break; - case ACPI_DMAR_TYPE_ATSR: + case ACPI_DMAR_TYPE_ROOT_ATS: ret = dmar_parse_one_atsr(entry_header); break; - case ACPI_DMAR_HARDWARE_AFFINITY: + case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: #ifdef CONFIG_ACPI_NUMA ret = dmar_parse_one_rhsa(entry_header); #endif break; - case ACPI_DMAR_TYPE_ANDD: + case ACPI_DMAR_TYPE_NAMESPACE: ret = dmar_parse_one_andd(entry_header); break; default: @@ -632,7 +632,7 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number, for (scope = (void *)(drhd + 1); (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; scope = ((void *)scope) + scope->length) { - if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI) + if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) continue; if (scope->enumeration_id != device_number) continue; @@ -667,21 +667,21 @@ static int __init dmar_acpi_dev_scope_init(void) for (andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar); ((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length; andd = ((void *)andd) + andd->header.length) { - if (andd->header.type == ACPI_DMAR_TYPE_ANDD) { + if (andd->header.type == ACPI_DMAR_TYPE_NAMESPACE) { acpi_handle h; struct acpi_device *adev; if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, - andd->object_name, + andd->device_name, &h))) { pr_err("Failed to find handle for ACPI object %s\n", - andd->object_name); + andd->device_name); continue; } acpi_bus_get_device(h, &adev); if (!adev) { pr_err("Failed to get device for ACPI object %s\n", - andd->object_name); + andd->device_name); continue; } dmar_acpi_insert_dev_scope(andd->device_number, adev); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 602d153c7055..70741c8c46a0 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -80,8 +80,9 @@ static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) return NULL; context->refcount = 1; - acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL, - acpiphp_post_dock_fixup); + context->hp.notify = acpiphp_hotplug_notify; + context->hp.fixup = acpiphp_post_dock_fixup; + acpi_set_hp_context(adev, &context->hp); return context; } @@ -369,20 +370,6 @@ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, return AE_OK; } -static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) -{ - struct acpiphp_bridge *bridge = NULL; - - acpi_lock_hp_context(); - if (adev->hp) { - bridge = to_acpiphp_root_context(adev->hp)->root_bridge; - if (bridge) - get_bridge(bridge); - } - acpi_unlock_hp_context(); - return bridge; -} - static void cleanup_bridge(struct acpiphp_bridge *bridge) { struct acpiphp_slot *slot; @@ -753,9 +740,15 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) void acpiphp_check_host_bridge(struct acpi_device *adev) { - struct acpiphp_bridge *bridge; + struct acpiphp_bridge *bridge = NULL; - bridge = acpiphp_dev_to_bridge(adev); + acpi_lock_hp_context(); + if (adev->hp) { + bridge = to_acpiphp_root_context(adev->hp)->root_bridge; + if (bridge) + get_bridge(bridge); + } + acpi_unlock_hp_context(); if (bridge) { pci_lock_rescan_remove(); @@ -884,7 +877,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) goto err; root_context->root_bridge = bridge; - acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL); + acpi_set_hp_context(adev, &root_context->hp); } else { struct acpiphp_context *context; @@ -927,7 +920,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) kfree(bridge); } -void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) +static void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) { if (pci_is_root_bus(bridge->pci_bus)) { struct acpiphp_root_context *root_context; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index ca4927ba8433..37263b0ebfe3 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -18,31 +18,31 @@ #include "pci.h" /** - * pci_acpi_wake_bus - Wake-up notification handler for root buses. - * @handle: ACPI handle of a device the notification is for. - * @event: Type of the signaled event. - * @context: PCI root bus to wake up devices on. + * pci_acpi_wake_bus - Root bus wakeup notification fork function. + * @work: Work item to handle. */ -static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) +static void pci_acpi_wake_bus(struct work_struct *work) { - struct pci_bus *pci_bus = context; + struct acpi_device *adev; + struct acpi_pci_root *root; - if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) - pci_pme_wakeup_bus(pci_bus); + adev = container_of(work, struct acpi_device, wakeup.context.work); + root = acpi_driver_data(adev); + pci_pme_wakeup_bus(root->bus); } /** - * pci_acpi_wake_dev - Wake-up notification handler for PCI devices. + * pci_acpi_wake_dev - PCI device wakeup notification work function. * @handle: ACPI handle of a device the notification is for. - * @event: Type of the signaled event. - * @context: PCI device object to wake up. + * @work: Work item to handle. */ -static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) +static void pci_acpi_wake_dev(struct work_struct *work) { - struct pci_dev *pci_dev = context; + struct acpi_device_wakeup_context *context; + struct pci_dev *pci_dev; - if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) - return; + context = container_of(work, struct acpi_device_wakeup_context, work); + pci_dev = to_pci_dev(context->dev); if (pci_dev->pme_poll) pci_dev->pme_poll = false; @@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) } /** - * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. - * @dev: ACPI device to add the notifier for. - * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. - */ -acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, - struct pci_bus *pci_bus) -{ - return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); -} - -/** - * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier. - * @dev: ACPI device to remove the notifier from. + * pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus. + * @dev: PCI root bridge ACPI device. */ -acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) +acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev) { - return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus); + return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus); } /** @@ -92,16 +81,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, struct pci_dev *pci_dev) { - return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); -} - -/** - * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier. - * @dev: ACPI device to remove the notifier from. - */ -acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) -{ - return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev); + return acpi_add_pm_notifier(dev, &pci_dev->dev, pci_acpi_wake_dev); } phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) @@ -170,14 +150,13 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) static bool acpi_pci_power_manageable(struct pci_dev *dev) { - acpi_handle handle = ACPI_HANDLE(&dev->dev); - - return handle ? acpi_bus_power_manageable(handle) : false; + struct acpi_device *adev = ACPI_COMPANION(&dev->dev); + return adev ? acpi_device_power_manageable(adev) : false; } static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { - acpi_handle handle = ACPI_HANDLE(&dev->dev); + struct acpi_device *adev = ACPI_COMPANION(&dev->dev); static const u8 state_conv[] = { [PCI_D0] = ACPI_STATE_D0, [PCI_D1] = ACPI_STATE_D1, @@ -188,7 +167,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) int error = -EINVAL; /* If the ACPI device has _EJ0, ignore the device */ - if (!handle || acpi_has_method(handle, "_EJ0")) + if (!adev || acpi_has_method(adev->handle, "_EJ0")) return -ENODEV; switch (state) { @@ -202,7 +181,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) case PCI_D1: case PCI_D2: case PCI_D3hot: - error = acpi_bus_set_power(handle, state_conv[state]); + error = acpi_device_set_power(adev, state_conv[state]); } if (!error) @@ -214,9 +193,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) static bool acpi_pci_can_wakeup(struct pci_dev *dev) { - acpi_handle handle = ACPI_HANDLE(&dev->dev); - - return handle ? acpi_bus_can_wakeup(handle) : false; + struct acpi_device *adev = ACPI_COMPANION(&dev->dev); + return adev ? acpi_device_can_wakeup(adev) : false; } static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index a5c6cb773e5f..d2b780aade89 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -67,8 +67,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) pnp_dbg(&dev->dev, "set resources\n"); - handle = ACPI_HANDLE(&dev->dev); - if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { + acpi_dev = ACPI_COMPANION(&dev->dev); + if (!acpi_dev) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return -ENODEV; } @@ -76,6 +76,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) if (WARN_ON_ONCE(acpi_dev != dev->data)) dev->data = acpi_dev; + handle = acpi_dev->handle; if (acpi_has_method(handle, METHOD_NAME__SRS)) { struct acpi_buffer buffer; @@ -93,8 +94,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) } kfree(buffer.pointer); } - if (!ret && acpi_bus_power_manageable(handle)) - ret = acpi_bus_set_power(handle, ACPI_STATE_D0); + if (!ret && acpi_device_power_manageable(acpi_dev)) + ret = acpi_device_set_power(acpi_dev, ACPI_STATE_D0); return ret; } @@ -102,23 +103,22 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) static int pnpacpi_disable_resources(struct pnp_dev *dev) { struct acpi_device *acpi_dev; - acpi_handle handle; acpi_status status; dev_dbg(&dev->dev, "disable resources\n"); - handle = ACPI_HANDLE(&dev->dev); - if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { + acpi_dev = ACPI_COMPANION(&dev->dev); + if (!acpi_dev) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return 0; } /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ - if (acpi_bus_power_manageable(handle)) - acpi_bus_set_power(handle, ACPI_STATE_D3_COLD); + if (acpi_device_power_manageable(acpi_dev)) + acpi_device_set_power(acpi_dev, ACPI_STATE_D3_COLD); - /* continue even if acpi_bus_set_power() fails */ - status = acpi_evaluate_object(handle, "_DIS", NULL, NULL); + /* continue even if acpi_device_set_power() fails */ + status = acpi_evaluate_object(acpi_dev->handle, "_DIS", NULL, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) return -ENODEV; @@ -128,26 +128,22 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) #ifdef CONFIG_ACPI_SLEEP static bool pnpacpi_can_wakeup(struct pnp_dev *dev) { - struct acpi_device *acpi_dev; - acpi_handle handle; + struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev); - handle = ACPI_HANDLE(&dev->dev); - if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { + if (!acpi_dev) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return false; } - return acpi_bus_can_wakeup(handle); + return acpi_bus_can_wakeup(acpi_dev->handle); } static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) { - struct acpi_device *acpi_dev; - acpi_handle handle; + struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev); int error = 0; - handle = ACPI_HANDLE(&dev->dev); - if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { + if (!acpi_dev) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return 0; } @@ -159,7 +155,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) return error; } - if (acpi_bus_power_manageable(handle)) { + if (acpi_device_power_manageable(acpi_dev)) { int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL, ACPI_STATE_D3_COLD); if (power_state < 0) @@ -167,12 +163,12 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) ACPI_STATE_D0 : ACPI_STATE_D3_COLD; /* - * acpi_bus_set_power() often fails (keyboard port can't be + * acpi_device_set_power() can fail (keyboard port can't be * powered-down?), and in any case, our return value is ignored * by pnp_bus_suspend(). Hence we don't revert the wakeup * setting if the set_power fails. */ - error = acpi_bus_set_power(handle, power_state); + error = acpi_device_set_power(acpi_dev, power_state); } return error; @@ -180,11 +176,10 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) static int pnpacpi_resume(struct pnp_dev *dev) { - struct acpi_device *acpi_dev; - acpi_handle handle = ACPI_HANDLE(&dev->dev); + struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev); int error = 0; - if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { + if (!acpi_dev) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return -ENODEV; } @@ -192,8 +187,8 @@ static int pnpacpi_resume(struct pnp_dev *dev) if (device_may_wakeup(&dev->dev)) acpi_pm_device_sleep_wake(&dev->dev, false); - if (acpi_bus_power_manageable(handle)) - error = acpi_bus_set_power(handle, ACPI_STATE_D0); + if (acpi_device_power_manageable(acpi_dev)) + error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0); return error; } @@ -295,9 +290,11 @@ static int __init pnpacpi_add_device(struct acpi_device *device) return error; } + error = acpi_bind_one(&dev->dev, device); + num++; - return 0; + return error; } static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, @@ -313,40 +310,6 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, return AE_OK; } -static int __init acpi_pnp_match(struct device *dev, void *_pnp) -{ - struct acpi_device *acpi = to_acpi_device(dev); - struct pnp_dev *pnp = _pnp; - - /* true means it matched */ - return pnp->data == acpi; -} - -static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev) -{ - dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev), - acpi_pnp_match); - if (!dev) - return NULL; - - put_device(dev); - return to_acpi_device(dev); -} - -/* complete initialization of a PNPACPI device includes having - * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. - */ -static bool acpi_pnp_bus_match(struct device *dev) -{ - return dev->bus == &pnp_bus_type; -} - -static struct acpi_bus_type __initdata acpi_pnp_bus = { - .name = "PNP", - .match = acpi_pnp_bus_match, - .find_companion = acpi_pnp_find_companion, -}; - int pnpacpi_disabled __initdata; static int __init pnpacpi_init(void) { @@ -356,10 +319,8 @@ static int __init pnpacpi_init(void) } printk(KERN_INFO "pnp: PnP ACPI init\n"); pnp_register_protocol(&pnpacpi_protocol); - register_acpi_bus_type(&acpi_pnp_bus); acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL); printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num); - unregister_acpi_bus_type(&acpi_pnp_bus); pnp_platform_devices = 1; return 0; } diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 932a60d6ed82..5a0a3e5daf85 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -219,6 +219,24 @@ /****************************************************************************** * + * Miscellaneous constants + * + *****************************************************************************/ + +/* UUID constants */ + +#define UUID_BUFFER_LENGTH 16 /* Length of UUID in memory */ +#define UUID_STRING_LENGTH 36 /* Total length of a UUID string */ + +/* Positions for required hyphens (dashes) in UUID strings */ + +#define UUID_HYPHEN1_OFFSET 8 +#define UUID_HYPHEN2_OFFSET 13 +#define UUID_HYPHEN3_OFFSET 18 +#define UUID_HYPHEN4_OFFSET 23 + +/****************************************************************************** + * * ACPI AML Debugger * *****************************************************************************/ diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 3dd6e838dc30..c728113374f5 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -55,6 +55,7 @@ #define METHOD_NAME__HID "_HID" #define METHOD_NAME__INI "_INI" #define METHOD_NAME__PLD "_PLD" +#define METHOD_NAME__DSD "_DSD" #define METHOD_NAME__PRS "_PRS" #define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__PRW "_PRW" diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b5714580801a..bcfd808b1098 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -315,12 +315,19 @@ struct acpi_device_wakeup_flags { u8 notifier_present:1; /* Wake-up notify handler has been installed */ }; +struct acpi_device_wakeup_context { + struct work_struct work; + struct device *dev; +}; + struct acpi_device_wakeup { acpi_handle gpe_device; u64 gpe_number; u64 sleep_state; struct list_head resources; struct acpi_device_wakeup_flags flags; + struct acpi_device_wakeup_context context; + struct wakeup_source *ws; int prepare_count; }; @@ -372,15 +379,9 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) } static inline void acpi_set_hp_context(struct acpi_device *adev, - struct acpi_hotplug_context *hp, - int (*notify)(struct acpi_device *, u32), - void (*uevent)(struct acpi_device *, u32), - void (*fixup)(struct acpi_device *)) + struct acpi_hotplug_context *hp) { hp->self = adev; - hp->notify = notify; - hp->uevent = uevent; - hp->fixup = fixup; adev->hp = hp; } @@ -487,6 +488,8 @@ struct acpi_bus_type { }; int register_acpi_bus_type(struct acpi_bus_type *); int unregister_acpi_bus_type(struct acpi_bus_type *); +int acpi_bind_one(struct device *dev, struct acpi_device *adev); +int acpi_unbind_one(struct device *dev); struct acpi_pci_root { struct acpi_device * device; @@ -510,20 +513,18 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); int acpi_disable_wakeup_device_power(struct acpi_device *dev); #ifdef CONFIG_PM -acpi_status acpi_add_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler, void *context); -acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler); +acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, + void (*work_func)(struct work_struct *work)); +acpi_status acpi_remove_pm_notifier(struct acpi_device *adev); int acpi_pm_device_sleep_state(struct device *, int *, int); #else static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler, - void *context) + struct device *dev, + void (*work_func)(struct work_struct *work)) { return AE_SUPPORT; } -static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, - acpi_notify_handler handler) +static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) { return AE_SUPPORT; } @@ -538,13 +539,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) #endif #ifdef CONFIG_PM_RUNTIME -int __acpi_device_run_wake(struct acpi_device *, bool); int acpi_pm_device_run_wake(struct device *, bool); #else -static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en) -{ - return -ENODEV; -} static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) { return -ENODEV; @@ -552,14 +548,8 @@ static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) #endif #ifdef CONFIG_PM_SLEEP -int __acpi_device_sleep_wake(struct acpi_device *, u32, bool); int acpi_pm_device_sleep_wake(struct device *, bool); #else -static inline int __acpi_device_sleep_wake(struct acpi_device *adev, - u32 target_state, bool enable) -{ - return -ENODEV; -} static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) { return -ENODEV; diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index f6f5f8af2112..03b3e6d405ff 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -399,4 +399,35 @@ char *acpi_os_get_next_filename(void *dir_handle); void acpi_os_close_directory(void *dir_handle); #endif +/* + * File I/O and related support + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_file +ACPI_FILE acpi_os_open_file(const char *path, u8 modes); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_file +void acpi_os_close_file(ACPI_FILE file); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_file +int +acpi_os_read_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_file +int +acpi_os_write_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_file_offset +long acpi_os_get_file_offset(ACPI_FILE file); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_set_file_offset +acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from); +#endif + #endif /* __ACPIOSXF_H__ */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 35b525c19711..b7c89d47efbe 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,15 +46,13 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20140424 +#define ACPI_CA_VERSION 0x20140724 #include <acpi/acconfig.h> #include <acpi/actypes.h> #include <acpi/actbl.h> #include <acpi/acbuffer.h> -extern u8 acpi_gbl_permanent_mmap; - /***************************************************************************** * * Macros used for ACPICA globals and configuration @@ -335,6 +333,23 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running); #endif /* ACPI_DEBUG_OUTPUT */ +/* + * Application prototypes + * + * All interfaces used by application will be configured + * out of the ACPICA build unless the ACPI_APPLICATION + * flag is defined. + */ +#ifdef ACPI_APPLICATION +#define ACPI_APP_DEPENDENT_RETURN_VOID(prototype) \ + prototype; + +#else +#define ACPI_APP_DEPENDENT_RETURN_VOID(prototype) \ + static ACPI_INLINE prototype {return;} + +#endif /* ACPI_APPLICATION */ + /***************************************************************************** * * ACPICA public interface prototypes @@ -658,6 +673,10 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status u32 gpe_number)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_mark_gpe_for_wake(acpi_handle gpe_device, + u32 gpe_number)) + +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_setup_gpe_for_wake(acpi_handle parent_device, acpi_handle gpe_device, @@ -861,21 +880,32 @@ ACPI_DBG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(6) const char *module_name, u32 component_id, const char *format, ...)) +ACPI_APP_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(1) + void ACPI_INTERNAL_VAR_XFACE + acpi_log_error(const char *format, ...)) /* * Divergences */ -acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type); +ACPI_GLOBAL(u8, acpi_gbl_permanent_mmap); -acpi_status acpi_unload_table_id(acpi_owner_id id); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_id(acpi_handle object, + acpi_owner_id * out_type)) -acpi_status -acpi_get_table_with_size(acpi_string signature, - u32 instance, struct acpi_table_header **out_table, - acpi_size *tbl_size); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_unload_table_id(acpi_owner_id id)) -acpi_status -acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data, - void (*callback)(void *)); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_table_with_size(acpi_string signature, + u32 instance, + struct acpi_table_header + **out_table, + acpi_size *tbl_size)) + +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_data_full(acpi_handle object, + acpi_object_handler handler, + void **data, + void (*callback)(void *))) #endif /* __ACXFACE_H__ */ diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 1cc7ef13c01a..bee19d8170c5 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -270,7 +270,8 @@ struct acpi_table_fadt { u32 flags; /* Miscellaneous flag bits (see below for individual flags) */ struct acpi_generic_address reset_register; /* 64-bit address of the Reset register */ u8 reset_value; /* Value to write to the reset_register port to reset the system */ - u8 reserved4[3]; /* Reserved, must be zero */ + u16 arm_boot_flags; /* ARM-Specific Boot Flags (see below for individual flags) (ACPI 5.1) */ + u8 minor_revision; /* FADT Minor Revision (ACPI 5.1) */ u64 Xfacs; /* 64-bit physical address of FACS */ u64 Xdsdt; /* 64-bit physical address of DSDT */ struct acpi_generic_address xpm1a_event_block; /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ @@ -285,7 +286,7 @@ struct acpi_table_fadt { struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register (ACPI 5.0) */ }; -/* Masks for FADT Boot Architecture Flags (boot_flags) [Vx]=Introduced in this FADT revision */ +/* Masks for FADT IA-PC Boot Architecture Flags (boot_flags) [Vx]=Introduced in this FADT revision */ #define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */ #define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */ @@ -296,6 +297,11 @@ struct acpi_table_fadt { #define FADT2_REVISION_ID 3 +/* Masks for FADT ARM Boot Architecture Flags (arm_boot_flags) ACPI 5.1 */ + +#define ACPI_FADT_PSCI_COMPLIANT (1) /* 00: [V5+] PSCI 0.2+ is implemented */ +#define ACPI_FADT_PSCI_USE_HVC (1<<1) /* 01: [V5+] HVC must be used instead of SMC as the PSCI conduit */ + /* Masks for FADT flags */ #define ACPI_FADT_WBINVD (1) /* 00: [V1] The WBINVD instruction works properly */ @@ -399,7 +405,7 @@ struct acpi_table_desc { * FADT V5 size: 0x10C */ #define ACPI_FADT_V1_SIZE (u32) (ACPI_FADT_OFFSET (flags) + 4) -#define ACPI_FADT_V2_SIZE (u32) (ACPI_FADT_OFFSET (reserved4[0]) + 3) +#define ACPI_FADT_V2_SIZE (u32) (ACPI_FADT_OFFSET (minor_revision) + 1) #define ACPI_FADT_V3_SIZE (u32) (ACPI_FADT_OFFSET (sleep_control)) #define ACPI_FADT_V5_SIZE (u32) (sizeof (struct acpi_table_fadt)) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 4ad7da805180..7626bfeac2cb 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -604,7 +604,7 @@ struct acpi_hest_generic { /* Generic Error Status block */ -struct acpi_generic_status { +struct acpi_hest_generic_status { u32 block_status; u32 raw_data_offset; u32 raw_data_length; @@ -614,15 +614,15 @@ struct acpi_generic_status { /* Values for block_status flags above */ -#define ACPI_GEN_ERR_UC BIT(0) -#define ACPI_GEN_ERR_CE BIT(1) -#define ACPI_GEN_ERR_MULTI_UC BIT(2) -#define ACPI_GEN_ERR_MULTI_CE BIT(3) -#define ACPI_GEN_ERR_COUNT_SHIFT (0xFF<<4) /* 8 bits, error count */ +#define ACPI_HEST_UNCORRECTABLE (1) +#define ACPI_HEST_CORRECTABLE (1<<1) +#define ACPI_HEST_MULTIPLE_UNCORRECTABLE (1<<2) +#define ACPI_HEST_MULTIPLE_CORRECTABLE (1<<3) +#define ACPI_HEST_ERROR_ENTRY_COUNT (0xFF<<4) /* 8 bits, error count */ /* Generic Error Data entry */ -struct acpi_generic_data { +struct acpi_hest_generic_data { u8 section_type[16]; u32 error_severity; u16 revision; @@ -671,7 +671,9 @@ enum acpi_madt_type { ACPI_MADT_TYPE_LOCAL_X2APIC_NMI = 10, ACPI_MADT_TYPE_GENERIC_INTERRUPT = 11, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR = 12, - ACPI_MADT_TYPE_RESERVED = 13 /* 13 and greater are reserved */ + ACPI_MADT_TYPE_GENERIC_MSI_FRAME = 13, + ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR = 14, + ACPI_MADT_TYPE_RESERVED = 15 /* 15 and greater are reserved */ }; /* @@ -797,15 +799,26 @@ struct acpi_madt_local_x2apic_nmi { struct acpi_madt_generic_interrupt { struct acpi_subtable_header header; u16 reserved; /* reserved - must be zero */ - u32 gic_id; + u32 cpu_interface_number; u32 uid; u32 flags; u32 parking_version; u32 performance_interrupt; u64 parked_address; u64 base_address; + u64 gicv_base_address; + u64 gich_base_address; + u32 vgic_interrupt; + u64 gicr_base_address; + u64 arm_mpidr; }; +/* Masks for Flags field above */ + +/* ACPI_MADT_ENABLED (1) Processor is usable if set */ +#define ACPI_MADT_PERFORMANCE_IRQ_MODE (1<<1) /* 01: Performance Interrupt Mode */ +#define ACPI_MADT_VGIC_IRQ_MODE (1<<2) /* 02: VGIC Maintenance Interrupt mode */ + /* 12: Generic Distributor (ACPI 5.0) */ struct acpi_madt_generic_distributor { @@ -817,11 +830,36 @@ struct acpi_madt_generic_distributor { u32 reserved2; /* reserved - must be zero */ }; +/* 13: Generic MSI Frame (ACPI 5.1) */ + +struct acpi_madt_generic_msi_frame { + struct acpi_subtable_header header; + u16 reserved; /* reserved - must be zero */ + u32 msi_frame_id; + u64 base_address; + u32 flags; + u16 spi_count; + u16 spi_base; +}; + +/* Masks for Flags field above */ + +#define ACPI_MADT_OVERRIDE_SPI_VALUES (1) + +/* 14: Generic Redistributor (ACPI 5.1) */ + +struct acpi_madt_generic_redistributor { + struct acpi_subtable_header header; + u16 reserved; /* reserved - must be zero */ + u64 base_address; + u32 length; +}; + /* * Common flags fields for MADT subtables */ -/* MADT Local APIC flags (lapic_flags) and GIC flags */ +/* MADT Local APIC flags */ #define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */ diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 860e5c883eb3..ecff62405f17 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -396,7 +396,7 @@ struct acpi_table_dbgp { * Version 1 * * Conforms to "Intel Virtualization Technology for Directed I/O", - * Version 1.2, Sept. 2008 + * Version 2.2, Sept. 2013 * ******************************************************************************/ @@ -423,9 +423,9 @@ struct acpi_dmar_header { enum acpi_dmar_type { ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, - ACPI_DMAR_TYPE_ATSR = 2, - ACPI_DMAR_HARDWARE_AFFINITY = 3, - ACPI_DMAR_TYPE_ANDD = 4, + ACPI_DMAR_TYPE_ROOT_ATS = 2, + ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, + ACPI_DMAR_TYPE_NAMESPACE = 4, ACPI_DMAR_TYPE_RESERVED = 5 /* 5 and greater are reserved */ }; @@ -439,7 +439,7 @@ struct acpi_dmar_device_scope { u8 bus; }; -/* Values for entry_type in struct acpi_dmar_device_scope */ +/* Values for entry_type in struct acpi_dmar_device_scope - device types */ enum acpi_dmar_scope_type { ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0, @@ -447,7 +447,7 @@ enum acpi_dmar_scope_type { ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2, ACPI_DMAR_SCOPE_TYPE_IOAPIC = 3, ACPI_DMAR_SCOPE_TYPE_HPET = 4, - ACPI_DMAR_SCOPE_TYPE_ACPI = 5, + ACPI_DMAR_SCOPE_TYPE_NAMESPACE = 5, ACPI_DMAR_SCOPE_TYPE_RESERVED = 6 /* 6 and greater are reserved */ }; @@ -516,7 +516,7 @@ struct acpi_dmar_andd { struct acpi_dmar_header header; u8 reserved[3]; u8 device_number; - u8 object_name[]; + char device_name[1]; }; /******************************************************************************* diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index c2295cc4a5c0..787bcc814463 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -241,33 +241,96 @@ struct acpi_s3pt_suspend { /******************************************************************************* * - * GTDT - Generic Timer Description Table (ACPI 5.0) - * Version 1 + * GTDT - Generic Timer Description Table (ACPI 5.1) + * Version 2 * ******************************************************************************/ struct acpi_table_gtdt { struct acpi_table_header header; /* Common ACPI table header */ - u64 address; - u32 flags; - u32 secure_pl1_interrupt; - u32 secure_pl1_flags; - u32 non_secure_pl1_interrupt; - u32 non_secure_pl1_flags; + u64 counter_block_addresss; + u32 reserved; + u32 secure_el1_interrupt; + u32 secure_el1_flags; + u32 non_secure_el1_interrupt; + u32 non_secure_el1_flags; u32 virtual_timer_interrupt; u32 virtual_timer_flags; - u32 non_secure_pl2_interrupt; - u32 non_secure_pl2_flags; + u32 non_secure_el2_interrupt; + u32 non_secure_el2_flags; + u64 counter_read_block_address; + u32 platform_timer_count; + u32 platform_timer_offset; }; -/* Values for Flags field above */ +/* Flag Definitions: Timer Block Physical Timers and Virtual timers */ + +#define ACPI_GTDT_INTERRUPT_MODE (1) +#define ACPI_GTDT_INTERRUPT_POLARITY (1<<1) +#define ACPI_GTDT_ALWAYS_ON (1<<2) + +/* Common GTDT subtable header */ + +struct acpi_gtdt_header { + u8 type; + u16 length; +}; -#define ACPI_GTDT_MAPPED_BLOCK_PRESENT 1 +/* Values for GTDT subtable type above */ -/* Values for all "TimerFlags" fields above */ +enum acpi_gtdt_type { + ACPI_GTDT_TYPE_TIMER_BLOCK = 0, + ACPI_GTDT_TYPE_WATCHDOG = 1, + ACPI_GTDT_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* GTDT Subtables, correspond to Type in struct acpi_gtdt_header */ + +/* 0: Generic Timer Block */ + +struct acpi_gtdt_timer_block { + struct acpi_gtdt_header header; + u8 reserved; + u64 block_address; + u32 timer_count; + u32 timer_offset; +}; + +/* Timer Sub-Structure, one per timer */ + +struct acpi_gtdt_timer_entry { + u8 frame_number; + u8 reserved[3]; + u64 base_address; + u64 el0_base_address; + u32 timer_interrupt; + u32 timer_flags; + u32 virtual_timer_interrupt; + u32 virtual_timer_flags; + u32 common_flags; +}; -#define ACPI_GTDT_INTERRUPT_MODE 1 -#define ACPI_GTDT_INTERRUPT_POLARITY 2 +/* Flag Definitions: common_flags above */ + +#define ACPI_GTDT_GT_IS_SECURE_TIMER (1) +#define ACPI_GTDT_GT_ALWAYS_ON (1<<1) + +/* 1: SBSA Generic Watchdog Structure */ + +struct acpi_gtdt_watchdog { + struct acpi_gtdt_header header; + u8 reserved; + u64 refresh_frame_address; + u64 control_frame_address; + u32 timer_interrupt; + u32 timer_flags; +}; + +/* Flag Definitions: timer_flags above */ + +#define ACPI_GTDT_WATCHDOG_IRQ_MODE (1) +#define ACPI_GTDT_WATCHDOG_IRQ_POLARITY (1<<1) +#define ACPI_GTDT_WATCHDOG_SECURE (1<<2) /******************************************************************************* * @@ -385,7 +448,8 @@ struct acpi_table_pcct { enum acpi_pcct_type { ACPI_PCCT_TYPE_GENERIC_SUBSPACE = 0, - ACPI_PCCT_TYPE_RESERVED = 1 /* 1 and greater are reserved */ + ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE = 1, + ACPI_PCCT_TYPE_RESERVED = 2 /* 2 and greater are reserved */ }; /* @@ -407,6 +471,28 @@ struct acpi_pcct_subspace { u16 min_turnaround_time; }; +/* 1: HW-reduced Communications Subspace (ACPI 5.1) */ + +struct acpi_pcct_hw_reduced { + struct acpi_subtable_header header; + u32 doorbell_interrupt; + u8 flags; + u8 reserved; + u64 base_address; + u64 length; + struct acpi_generic_address doorbell_register; + u64 preserve_mask; + u64 write_mask; + u32 latency; + u32 max_access_rate; + u16 min_turnaround_time; +}; + +/* Values for doorbell flags above */ + +#define ACPI_PCCT_INTERRUPT_POLARITY (1) +#define ACPI_PCCT_INTERRUPT_MODE (1<<1) + /* * PCC memory structures (not part of the ACPI table) */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 19b26bb69a70..ac03ec81d342 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -126,6 +126,7 @@ typedef unsigned char u8; typedef unsigned char u8; typedef unsigned short u16; +typedef short s16; typedef COMPILER_DEPENDENT_UINT64 u64; typedef COMPILER_DEPENDENT_INT64 s64; @@ -516,7 +517,7 @@ typedef u64 acpi_integer; #define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL,(acpi_size) i) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) NULL) -#define ACPI_OFFSET(d, f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f), (void *) NULL) +#define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) NULL) #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) @@ -611,8 +612,9 @@ typedef u64 acpi_integer; #define ACPI_NOTIFY_RESERVED (u8) 0x0A #define ACPI_NOTIFY_LOCALITY_UPDATE (u8) 0x0B #define ACPI_NOTIFY_SHUTDOWN_REQUEST (u8) 0x0C +#define ACPI_NOTIFY_AFFINITY_UPDATE (u8) 0x0D -#define ACPI_NOTIFY_MAX 0x0C +#define ACPI_NOTIFY_MAX 0x0D /* * Types associated with ACPI names and objects. The first group of @@ -1244,4 +1246,17 @@ struct acpi_memory_list { #define ACPI_OSI_WIN_7 0x0B #define ACPI_OSI_WIN_8 0x0C +/* Definitions of file IO */ + +#define ACPI_FILE_READING 0x01 +#define ACPI_FILE_WRITING 0x02 +#define ACPI_FILE_BINARY 0x04 + +#define ACPI_FILE_BEGIN 0x01 +#define ACPI_FILE_END 0x02 + +/* Definitions of getopt */ + +#define ACPI_OPT_END -1 + #endif /* __ACTYPES_H__ */ diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index dfd60d0bfd27..720446cb243e 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -14,7 +14,7 @@ struct ghes { struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u64 buffer_paddr; unsigned long flags; union { diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index e863dd5c4e04..5f8cc1fa3278 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -87,20 +87,14 @@ #define ACPI_DBG_TRACK_ALLOCATIONS #endif -/* acpi_names configuration. Single threaded with debugger output enabled. */ - -#ifdef ACPI_NAMES_APP -#define ACPI_DEBUGGER -#define ACPI_APPLICATION -#define ACPI_SINGLE_THREADED -#endif - /* - * acpi_bin/acpi_dump/acpi_src/acpi_xtract/Example configuration. All single - * threaded, with no debug output. + * acpi_bin/acpi_dump/acpi_help/acpi_names/acpi_src/acpi_xtract/Example configuration. + * All single threaded. */ #if (defined ACPI_BIN_APP) || \ (defined ACPI_DUMP_APP) || \ + (defined ACPI_HELP_APP) || \ + (defined ACPI_NAMES_APP) || \ (defined ACPI_SRC_APP) || \ (defined ACPI_XTRACT_APP) || \ (defined ACPI_EXAMPLE_APP) @@ -108,12 +102,40 @@ #define ACPI_SINGLE_THREADED #endif +/* acpi_help configuration. Error messages disabled. */ + #ifdef ACPI_HELP_APP -#define ACPI_APPLICATION -#define ACPI_SINGLE_THREADED #define ACPI_NO_ERROR_MESSAGES #endif +/* acpi_names configuration. Debug output enabled. */ + +#ifdef ACPI_NAMES_APP +#define ACPI_DEBUG_OUTPUT +#endif + +/* acpi_exec/acpi_names/Example configuration. Native RSDP used. */ + +#if (defined ACPI_EXEC_APP) || \ + (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_USE_NATIVE_RSDP_POINTER +#endif + +/* acpi_dump configuration. Native mapping used if provied by OSPMs */ + +#ifdef ACPI_DUMP_APP +#define ACPI_USE_NATIVE_MEMORY_MAPPING +#define USE_NATIVE_ALLOCATE_ZEROED +#endif + +/* acpi_names/Example configuration. Hardware disabled */ + +#if (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_REDUCED_HARDWARE 1 +#endif + /* Linkable ACPICA library */ #ifdef ACPI_LIBRARY @@ -185,6 +207,9 @@ #elif defined(_AED_EFI) #include "acefi.h" +#elif defined(_GNU_EFI) +#include "acefi.h" + #elif defined(__HAIKU__) #include "achaiku.h" @@ -399,8 +424,12 @@ typedef char *va_list; #ifdef ACPI_APPLICATION #include <stdio.h> #define ACPI_FILE FILE * +#define ACPI_FILE_OUT stdout +#define ACPI_FILE_ERR stderr #else #define ACPI_FILE void * +#define ACPI_FILE_OUT NULL +#define ACPI_FILE_ERR NULL #endif /* ACPI_APPLICATION */ #endif /* ACPI_FILE */ diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index cd1f052d55bb..1ba7c190c2cc 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -44,6 +44,16 @@ #ifndef __ACLINUX_H__ #define __ACLINUX_H__ +#ifdef __KERNEL__ + +/* ACPICA external files should not include ACPICA headers directly. */ + +#if !defined(BUILDING_ACPICA) && !defined(_LINUX_ACPI_H) +#error "Please don't include <acpi/acpi.h> directly, include <linux/acpi.h> instead." +#endif + +#endif + /* Common (in-kernel/user-space) ACPICA configuration */ #define ACPI_USE_SYSTEM_CLIBRARY @@ -70,7 +80,9 @@ #ifdef EXPORT_ACPI_INTERFACES #include <linux/export.h> #endif +#ifdef CONFIG_ACPI #include <asm/acenv.h> +#endif #ifndef CONFIG_ACPI diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index 191e741cfa0e..568d4b886712 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -46,6 +46,28 @@ #ifdef __KERNEL__ +#ifndef ACPI_USE_NATIVE_DIVIDE + +#ifndef ACPI_DIV_64_BY_32 +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ + do { \ + u64 (__n) = ((u64) n_hi) << 32 | (n_lo); \ + (r32) = do_div ((__n), (d32)); \ + (q32) = (u32) (__n); \ + } while (0) +#endif + +#ifndef ACPI_SHIFT_RIGHT_64 +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ + do { \ + (n_lo) >>= 1; \ + (n_lo) |= (((n_hi) & 1) << 31); \ + (n_hi) >>= 1; \ + } while (0) +#endif + +#endif + /* * Overrides for in-kernel ACPICA */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 358c01b971db..5320153c311b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -29,17 +29,17 @@ #include <linux/ioport.h> /* for struct resource */ #include <linux/device.h> -#ifdef CONFIG_ACPI - #ifndef _LINUX #define _LINUX #endif +#include <acpi/acpi.h> + +#ifdef CONFIG_ACPI #include <linux/list.h> #include <linux/mod_devicetable.h> #include <linux/dynamic_debug.h> -#include <acpi/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <acpi/acpi_numa.h> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 8f8ae95c6e27..7d1955afa62c 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -176,6 +176,7 @@ static inline void disable_cpufreq(void) { } #define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ +#define CPUFREQ_RELATION_C 2 /* closest frequency to target */ struct freq_attr { struct attribute attr; diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 637a608ded0b..64dacb7288a6 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -11,12 +11,17 @@ #include <linux/acpi.h> #ifdef CONFIG_ACPI -extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, - struct pci_bus *pci_bus); -extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); +extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev); +static inline acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) +{ + return acpi_remove_pm_notifier(dev); +} extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, struct pci_dev *pci_dev); -extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); +static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) +{ + return acpi_remove_pm_notifier(dev); +} extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle); static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 43fd6716f662..367f49b9a1c9 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -24,11 +24,20 @@ #define RPM_AUTO 0x08 /* Use autosuspend_delay */ #ifdef CONFIG_PM +extern struct workqueue_struct *pm_wq; + +static inline bool queue_pm_work(struct work_struct *work) +{ + return queue_work(pm_wq, work); +} + extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev); extern int pm_runtime_force_suspend(struct device *dev); extern int pm_runtime_force_resume(struct device *dev); #else +static inline bool queue_pm_work(struct work_struct *work) { return false; } + static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline int pm_runtime_force_suspend(struct device *dev) { return 0; } @@ -37,8 +46,6 @@ static inline int pm_runtime_force_resume(struct device *dev) { return 0; } #ifdef CONFIG_PM_RUNTIME -extern struct workqueue_struct *pm_wq; - extern int __pm_runtime_idle(struct device *dev, int rpmflags); extern int __pm_runtime_suspend(struct device *dev, int rpmflags); extern int __pm_runtime_resume(struct device *dev, int rpmflags); diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h index 4723bbfa1c26..a6e555cbe05c 100644 --- a/include/linux/sfi_acpi.h +++ b/include/linux/sfi_acpi.h @@ -63,8 +63,6 @@ #include <linux/sfi.h> #ifdef CONFIG_SFI -#include <acpi/acpi.h> /* FIXME: inclusion should be removed */ - extern int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, int (*handler)(struct acpi_table_header *)); @@ -78,7 +76,6 @@ static inline int __init acpi_sfi_table_parse(char *signature, return sfi_acpi_table_parse(signature, NULL, NULL, handler); } #else /* !CONFIG_SFI */ - static inline int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, int (*handler)(struct acpi_table_header *)) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 9a83d780facd..e4e4121fa327 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -253,9 +253,6 @@ config APM_EMULATION anything, try disabling/enabling this option (or disabling/enabling APM in your BIOS). -config ARCH_HAS_OPP - bool - config PM_OPP bool ---help--- diff --git a/kernel/power/main.c b/kernel/power/main.c index 8e90f330f139..9a59d042ea84 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -296,8 +296,8 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, suspend_state_t i; for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) - if (pm_states[i].state) - s += sprintf(s,"%s ", pm_states[i].label); + if (pm_states[i]) + s += sprintf(s,"%s ", pm_states[i]); #endif if (hibernation_available()) @@ -311,8 +311,7 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, static suspend_state_t decode_state(const char *buf, size_t n) { #ifdef CONFIG_SUSPEND - suspend_state_t state = PM_SUSPEND_MIN; - struct pm_sleep_state *s; + suspend_state_t state; #endif char *p; int len; @@ -325,10 +324,12 @@ static suspend_state_t decode_state(const char *buf, size_t n) return PM_SUSPEND_MAX; #ifdef CONFIG_SUSPEND - for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) - if (s->state && len == strlen(s->label) - && !strncmp(buf, s->label, len)) - return s->state; + for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) { + const char *label = pm_states[state]; + + if (label && len == strlen(label) && !strncmp(buf, label, len)) + return state; + } #endif return PM_SUSPEND_ON; @@ -446,8 +447,8 @@ static ssize_t autosleep_show(struct kobject *kobj, #ifdef CONFIG_SUSPEND if (state < PM_SUSPEND_MAX) - return sprintf(buf, "%s\n", pm_states[state].state ? - pm_states[state].label : "error"); + return sprintf(buf, "%s\n", pm_states[state] ? + pm_states[state] : "error"); #endif #ifdef CONFIG_HIBERNATION return sprintf(buf, "disk\n"); @@ -615,7 +616,6 @@ static struct attribute_group attr_group = { .attrs = g, }; -#ifdef CONFIG_PM_RUNTIME struct workqueue_struct *pm_wq; EXPORT_SYMBOL_GPL(pm_wq); @@ -625,9 +625,6 @@ static int __init pm_start_workqueue(void) return pm_wq ? 0 : -ENOMEM; } -#else -static inline int pm_start_workqueue(void) { return 0; } -#endif static int __init pm_init(void) { diff --git a/kernel/power/power.h b/kernel/power/power.h index c60f13b5270a..5d49dcac2537 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -178,13 +178,8 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *, unsigned int, char *); #ifdef CONFIG_SUSPEND -struct pm_sleep_state { - const char *label; - suspend_state_t state; -}; - /* kernel/power/suspend.c */ -extern struct pm_sleep_state pm_states[]; +extern const char *pm_states[]; extern int suspend_devices_and_enter(suspend_state_t state); #else /* !CONFIG_SUSPEND */ diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 1ea328aafdc9..4fc5c32422b3 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -248,33 +248,61 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size) * information is stored (in the form of a block of bitmap) * It also contains the pfns that correspond to the start and end of * the represented memory area. + * + * The memory bitmap is organized as a radix tree to guarantee fast random + * access to the bits. There is one radix tree for each zone (as returned + * from create_mem_extents). + * + * One radix tree is represented by one struct mem_zone_bm_rtree. There are + * two linked lists for the nodes of the tree, one for the inner nodes and + * one for the leave nodes. The linked leave nodes are used for fast linear + * access of the memory bitmap. + * + * The struct rtree_node represents one node of the radix tree. */ #define BM_END_OF_MAP (~0UL) #define BM_BITS_PER_BLOCK (PAGE_SIZE * BITS_PER_BYTE) +#define BM_BLOCK_SHIFT (PAGE_SHIFT + 3) +#define BM_BLOCK_MASK ((1UL << BM_BLOCK_SHIFT) - 1) -struct bm_block { - struct list_head hook; /* hook into a list of bitmap blocks */ - unsigned long start_pfn; /* pfn represented by the first bit */ - unsigned long end_pfn; /* pfn represented by the last bit plus 1 */ - unsigned long *data; /* bitmap representing pages */ +/* + * struct rtree_node is a wrapper struct to link the nodes + * of the rtree together for easy linear iteration over + * bits and easy freeing + */ +struct rtree_node { + struct list_head list; + unsigned long *data; }; -static inline unsigned long bm_block_bits(struct bm_block *bb) -{ - return bb->end_pfn - bb->start_pfn; -} +/* + * struct mem_zone_bm_rtree represents a bitmap used for one + * populated memory zone. + */ +struct mem_zone_bm_rtree { + struct list_head list; /* Link Zones together */ + struct list_head nodes; /* Radix Tree inner nodes */ + struct list_head leaves; /* Radix Tree leaves */ + unsigned long start_pfn; /* Zone start page frame */ + unsigned long end_pfn; /* Zone end page frame + 1 */ + struct rtree_node *rtree; /* Radix Tree Root */ + int levels; /* Number of Radix Tree Levels */ + unsigned int blocks; /* Number of Bitmap Blocks */ +}; /* strcut bm_position is used for browsing memory bitmaps */ struct bm_position { - struct bm_block *block; - int bit; + struct mem_zone_bm_rtree *zone; + struct rtree_node *node; + unsigned long node_pfn; + int node_bit; }; struct memory_bitmap { - struct list_head blocks; /* list of bitmap blocks */ + struct list_head zones; struct linked_page *p_list; /* list of pages used to store zone * bitmap objects and bitmap block * objects @@ -284,38 +312,178 @@ struct memory_bitmap { /* Functions that operate on memory bitmaps */ -static void memory_bm_position_reset(struct memory_bitmap *bm) +#define BM_ENTRIES_PER_LEVEL (PAGE_SIZE / sizeof(unsigned long)) +#if BITS_PER_LONG == 32 +#define BM_RTREE_LEVEL_SHIFT (PAGE_SHIFT - 2) +#else +#define BM_RTREE_LEVEL_SHIFT (PAGE_SHIFT - 3) +#endif +#define BM_RTREE_LEVEL_MASK ((1UL << BM_RTREE_LEVEL_SHIFT) - 1) + +/* + * alloc_rtree_node - Allocate a new node and add it to the radix tree. + * + * This function is used to allocate inner nodes as well as the + * leave nodes of the radix tree. It also adds the node to the + * corresponding linked list passed in by the *list parameter. + */ +static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed, + struct chain_allocator *ca, + struct list_head *list) { - bm->cur.block = list_entry(bm->blocks.next, struct bm_block, hook); - bm->cur.bit = 0; -} + struct rtree_node *node; -static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free); + node = chain_alloc(ca, sizeof(struct rtree_node)); + if (!node) + return NULL; -/** - * create_bm_block_list - create a list of block bitmap objects - * @pages - number of pages to track - * @list - list to put the allocated blocks into - * @ca - chain allocator to be used for allocating memory + node->data = get_image_page(gfp_mask, safe_needed); + if (!node->data) + return NULL; + + list_add_tail(&node->list, list); + + return node; +} + +/* + * add_rtree_block - Add a new leave node to the radix tree + * + * The leave nodes need to be allocated in order to keep the leaves + * linked list in order. This is guaranteed by the zone->blocks + * counter. */ -static int create_bm_block_list(unsigned long pages, - struct list_head *list, - struct chain_allocator *ca) +static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask, + int safe_needed, struct chain_allocator *ca) { - unsigned int nr_blocks = DIV_ROUND_UP(pages, BM_BITS_PER_BLOCK); + struct rtree_node *node, *block, **dst; + unsigned int levels_needed, block_nr; + int i; - while (nr_blocks-- > 0) { - struct bm_block *bb; + block_nr = zone->blocks; + levels_needed = 0; - bb = chain_alloc(ca, sizeof(struct bm_block)); - if (!bb) + /* How many levels do we need for this block nr? */ + while (block_nr) { + levels_needed += 1; + block_nr >>= BM_RTREE_LEVEL_SHIFT; + } + + /* Make sure the rtree has enough levels */ + for (i = zone->levels; i < levels_needed; i++) { + node = alloc_rtree_node(gfp_mask, safe_needed, ca, + &zone->nodes); + if (!node) return -ENOMEM; - list_add(&bb->hook, list); + + node->data[0] = (unsigned long)zone->rtree; + zone->rtree = node; + zone->levels += 1; + } + + /* Allocate new block */ + block = alloc_rtree_node(gfp_mask, safe_needed, ca, &zone->leaves); + if (!block) + return -ENOMEM; + + /* Now walk the rtree to insert the block */ + node = zone->rtree; + dst = &zone->rtree; + block_nr = zone->blocks; + for (i = zone->levels; i > 0; i--) { + int index; + + if (!node) { + node = alloc_rtree_node(gfp_mask, safe_needed, ca, + &zone->nodes); + if (!node) + return -ENOMEM; + *dst = node; + } + + index = block_nr >> ((i - 1) * BM_RTREE_LEVEL_SHIFT); + index &= BM_RTREE_LEVEL_MASK; + dst = (struct rtree_node **)&((*dst)->data[index]); + node = *dst; } + zone->blocks += 1; + *dst = block; + return 0; } +static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone, + int clear_nosave_free); + +/* + * create_zone_bm_rtree - create a radix tree for one zone + * + * Allocated the mem_zone_bm_rtree structure and initializes it. + * This function also allocated and builds the radix tree for the + * zone. + */ +static struct mem_zone_bm_rtree * +create_zone_bm_rtree(gfp_t gfp_mask, int safe_needed, + struct chain_allocator *ca, + unsigned long start, unsigned long end) +{ + struct mem_zone_bm_rtree *zone; + unsigned int i, nr_blocks; + unsigned long pages; + + pages = end - start; + zone = chain_alloc(ca, sizeof(struct mem_zone_bm_rtree)); + if (!zone) + return NULL; + + INIT_LIST_HEAD(&zone->nodes); + INIT_LIST_HEAD(&zone->leaves); + zone->start_pfn = start; + zone->end_pfn = end; + nr_blocks = DIV_ROUND_UP(pages, BM_BITS_PER_BLOCK); + + for (i = 0; i < nr_blocks; i++) { + if (add_rtree_block(zone, gfp_mask, safe_needed, ca)) { + free_zone_bm_rtree(zone, PG_UNSAFE_CLEAR); + return NULL; + } + } + + return zone; +} + +/* + * free_zone_bm_rtree - Free the memory of the radix tree + * + * Free all node pages of the radix tree. The mem_zone_bm_rtree + * structure itself is not freed here nor are the rtree_node + * structs. + */ +static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone, + int clear_nosave_free) +{ + struct rtree_node *node; + + list_for_each_entry(node, &zone->nodes, list) + free_image_page(node->data, clear_nosave_free); + + list_for_each_entry(node, &zone->leaves, list) + free_image_page(node->data, clear_nosave_free); +} + +static void memory_bm_position_reset(struct memory_bitmap *bm) +{ + bm->cur.zone = list_entry(bm->zones.next, struct mem_zone_bm_rtree, + list); + bm->cur.node = list_entry(bm->cur.zone->leaves.next, + struct rtree_node, list); + bm->cur.node_pfn = 0; + bm->cur.node_bit = 0; +} + +static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free); + struct mem_extent { struct list_head hook; unsigned long start; @@ -407,40 +575,22 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) int error; chain_init(&ca, gfp_mask, safe_needed); - INIT_LIST_HEAD(&bm->blocks); + INIT_LIST_HEAD(&bm->zones); error = create_mem_extents(&mem_extents, gfp_mask); if (error) return error; list_for_each_entry(ext, &mem_extents, hook) { - struct bm_block *bb; - unsigned long pfn = ext->start; - unsigned long pages = ext->end - ext->start; - - bb = list_entry(bm->blocks.prev, struct bm_block, hook); + struct mem_zone_bm_rtree *zone; - error = create_bm_block_list(pages, bm->blocks.prev, &ca); - if (error) + zone = create_zone_bm_rtree(gfp_mask, safe_needed, &ca, + ext->start, ext->end); + if (!zone) { + error = -ENOMEM; goto Error; - - list_for_each_entry_continue(bb, &bm->blocks, hook) { - bb->data = get_image_page(gfp_mask, safe_needed); - if (!bb->data) { - error = -ENOMEM; - goto Error; - } - - bb->start_pfn = pfn; - if (pages >= BM_BITS_PER_BLOCK) { - pfn += BM_BITS_PER_BLOCK; - pages -= BM_BITS_PER_BLOCK; - } else { - /* This is executed only once in the loop */ - pfn += pages; - } - bb->end_pfn = pfn; } + list_add_tail(&zone->list, &bm->zones); } bm->p_list = ca.chain; @@ -460,51 +610,83 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) */ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) { - struct bm_block *bb; + struct mem_zone_bm_rtree *zone; - list_for_each_entry(bb, &bm->blocks, hook) - if (bb->data) - free_image_page(bb->data, clear_nosave_free); + list_for_each_entry(zone, &bm->zones, list) + free_zone_bm_rtree(zone, clear_nosave_free); free_list_of_pages(bm->p_list, clear_nosave_free); - INIT_LIST_HEAD(&bm->blocks); + INIT_LIST_HEAD(&bm->zones); } /** - * memory_bm_find_bit - find the bit in the bitmap @bm that corresponds - * to given pfn. The cur_zone_bm member of @bm and the cur_block member - * of @bm->cur_zone_bm are updated. + * memory_bm_find_bit - Find the bit for pfn in the memory + * bitmap + * + * Find the bit in the bitmap @bm that corresponds to given pfn. + * The cur.zone, cur.block and cur.node_pfn member of @bm are + * updated. + * It walks the radix tree to find the page which contains the bit for + * pfn and returns the bit position in **addr and *bit_nr. */ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, - void **addr, unsigned int *bit_nr) + void **addr, unsigned int *bit_nr) { - struct bm_block *bb; + struct mem_zone_bm_rtree *curr, *zone; + struct rtree_node *node; + int i, block_nr; + zone = bm->cur.zone; + + if (pfn >= zone->start_pfn && pfn < zone->end_pfn) + goto zone_found; + + zone = NULL; + + /* Find the right zone */ + list_for_each_entry(curr, &bm->zones, list) { + if (pfn >= curr->start_pfn && pfn < curr->end_pfn) { + zone = curr; + break; + } + } + + if (!zone) + return -EFAULT; + +zone_found: /* - * Check if the pfn corresponds to the current bitmap block and find - * the block where it fits if this is not the case. + * We have a zone. Now walk the radix tree to find the leave + * node for our pfn. */ - bb = bm->cur.block; - if (pfn < bb->start_pfn) - list_for_each_entry_continue_reverse(bb, &bm->blocks, hook) - if (pfn >= bb->start_pfn) - break; - if (pfn >= bb->end_pfn) - list_for_each_entry_continue(bb, &bm->blocks, hook) - if (pfn >= bb->start_pfn && pfn < bb->end_pfn) - break; + node = bm->cur.node; + if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) + goto node_found; - if (&bb->hook == &bm->blocks) - return -EFAULT; + node = zone->rtree; + block_nr = (pfn - zone->start_pfn) >> BM_BLOCK_SHIFT; + + for (i = zone->levels; i > 0; i--) { + int index; + + index = block_nr >> ((i - 1) * BM_RTREE_LEVEL_SHIFT); + index &= BM_RTREE_LEVEL_MASK; + BUG_ON(node->data[index] == 0); + node = (struct rtree_node *)node->data[index]; + } + +node_found: + /* Update last position */ + bm->cur.zone = zone; + bm->cur.node = node; + bm->cur.node_pfn = (pfn - zone->start_pfn) & ~BM_BLOCK_MASK; + + /* Set return values */ + *addr = node->data; + *bit_nr = (pfn - zone->start_pfn) & BM_BLOCK_MASK; - /* The block has been found */ - bm->cur.block = bb; - pfn -= bb->start_pfn; - bm->cur.bit = pfn + 1; - *bit_nr = pfn; - *addr = bb->data; return 0; } @@ -528,6 +710,7 @@ static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) error = memory_bm_find_bit(bm, pfn, &addr, &bit); if (!error) set_bit(bit, addr); + return error; } @@ -542,6 +725,14 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) clear_bit(bit, addr); } +static void memory_bm_clear_current(struct memory_bitmap *bm) +{ + int bit; + + bit = max(bm->cur.node_bit - 1, 0); + clear_bit(bit, bm->cur.node->data); +} + static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) { void *addr; @@ -561,38 +752,70 @@ static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn) return !memory_bm_find_bit(bm, pfn, &addr, &bit); } -/** - * memory_bm_next_pfn - find the pfn that corresponds to the next set bit - * in the bitmap @bm. If the pfn cannot be found, BM_END_OF_MAP is - * returned. +/* + * rtree_next_node - Jumps to the next leave node + * + * Sets the position to the beginning of the next node in the + * memory bitmap. This is either the next node in the current + * zone's radix tree or the first node in the radix tree of the + * next zone. * - * It is required to run memory_bm_position_reset() before the first call to - * this function. + * Returns true if there is a next node, false otherwise. */ +static bool rtree_next_node(struct memory_bitmap *bm) +{ + bm->cur.node = list_entry(bm->cur.node->list.next, + struct rtree_node, list); + if (&bm->cur.node->list != &bm->cur.zone->leaves) { + bm->cur.node_pfn += BM_BITS_PER_BLOCK; + bm->cur.node_bit = 0; + touch_softlockup_watchdog(); + return true; + } + + /* No more nodes, goto next zone */ + bm->cur.zone = list_entry(bm->cur.zone->list.next, + struct mem_zone_bm_rtree, list); + if (&bm->cur.zone->list != &bm->zones) { + bm->cur.node = list_entry(bm->cur.zone->leaves.next, + struct rtree_node, list); + bm->cur.node_pfn = 0; + bm->cur.node_bit = 0; + return true; + } + /* No more zones */ + return false; +} + +/** + * memory_bm_rtree_next_pfn - Find the next set bit in the bitmap @bm + * + * Starting from the last returned position this function searches + * for the next set bit in the memory bitmap and returns its + * number. If no more bit is set BM_END_OF_MAP is returned. + * + * It is required to run memory_bm_position_reset() before the + * first call to this function. + */ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm) { - struct bm_block *bb; + unsigned long bits, pfn, pages; int bit; - bb = bm->cur.block; do { - bit = bm->cur.bit; - bit = find_next_bit(bb->data, bm_block_bits(bb), bit); - if (bit < bm_block_bits(bb)) - goto Return_pfn; - - bb = list_entry(bb->hook.next, struct bm_block, hook); - bm->cur.block = bb; - bm->cur.bit = 0; - } while (&bb->hook != &bm->blocks); + pages = bm->cur.zone->end_pfn - bm->cur.zone->start_pfn; + bits = min(pages - bm->cur.node_pfn, BM_BITS_PER_BLOCK); + bit = find_next_bit(bm->cur.node->data, bits, + bm->cur.node_bit); + if (bit < bits) { + pfn = bm->cur.zone->start_pfn + bm->cur.node_pfn + bit; + bm->cur.node_bit = bit + 1; + return pfn; + } + } while (rtree_next_node(bm)); - memory_bm_position_reset(bm); return BM_END_OF_MAP; - - Return_pfn: - bm->cur.bit = bit + 1; - return bb->start_pfn + bit; } /** @@ -816,12 +1039,17 @@ void free_basic_memory_bitmaps(void) unsigned int snapshot_additional_pages(struct zone *zone) { - unsigned int res; + unsigned int rtree, nodes; + + rtree = nodes = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK); + rtree += DIV_ROUND_UP(rtree * sizeof(struct rtree_node), + LINKED_PAGE_DATA_SIZE); + while (nodes > 1) { + nodes = DIV_ROUND_UP(nodes, BM_ENTRIES_PER_LEVEL); + rtree += nodes; + } - res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK); - res += DIV_ROUND_UP(res * sizeof(struct bm_block), - LINKED_PAGE_DATA_SIZE); - return 2 * res; + return 2 * rtree; } #ifdef CONFIG_HIGHMEM @@ -1094,23 +1322,35 @@ static struct memory_bitmap copy_bm; void swsusp_free(void) { - struct zone *zone; - unsigned long pfn, max_zone_pfn; + unsigned long fb_pfn, fr_pfn; - for_each_populated_zone(zone) { - max_zone_pfn = zone_end_pfn(zone); - for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) - if (pfn_valid(pfn)) { - struct page *page = pfn_to_page(pfn); - - if (swsusp_page_is_forbidden(page) && - swsusp_page_is_free(page)) { - swsusp_unset_page_forbidden(page); - swsusp_unset_page_free(page); - __free_page(page); - } - } + memory_bm_position_reset(forbidden_pages_map); + memory_bm_position_reset(free_pages_map); + +loop: + fr_pfn = memory_bm_next_pfn(free_pages_map); + fb_pfn = memory_bm_next_pfn(forbidden_pages_map); + + /* + * Find the next bit set in both bitmaps. This is guaranteed to + * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP. + */ + do { + if (fb_pfn < fr_pfn) + fb_pfn = memory_bm_next_pfn(forbidden_pages_map); + if (fr_pfn < fb_pfn) + fr_pfn = memory_bm_next_pfn(free_pages_map); + } while (fb_pfn != fr_pfn); + + if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) { + struct page *page = pfn_to_page(fr_pfn); + + memory_bm_clear_current(forbidden_pages_map); + memory_bm_clear_current(free_pages_map); + __free_page(page); + goto loop; } + nr_copy_pages = 0; nr_meta_pages = 0; restore_pblist = NULL; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 4b736b4dfa96..6dadb25cb0d8 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -31,20 +31,11 @@ #include "power.h" -struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = { - [PM_SUSPEND_FREEZE] = { .label = "freeze", .state = PM_SUSPEND_FREEZE }, - [PM_SUSPEND_STANDBY] = { .label = "standby", }, - [PM_SUSPEND_MEM] = { .label = "mem", }, -}; +static const char *pm_labels[] = { "mem", "standby", "freeze", }; +const char *pm_states[PM_SUSPEND_MAX]; static const struct platform_suspend_ops *suspend_ops; static const struct platform_freeze_ops *freeze_ops; - -static bool need_suspend_ops(suspend_state_t state) -{ - return state > PM_SUSPEND_FREEZE; -} - static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); static bool suspend_freeze_wake; @@ -97,10 +88,7 @@ static bool relative_states; static int __init sleep_states_setup(char *str) { relative_states = !strncmp(str, "1", 1); - if (relative_states) { - pm_states[PM_SUSPEND_MEM].state = PM_SUSPEND_FREEZE; - pm_states[PM_SUSPEND_FREEZE].state = 0; - } + pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2]; return 1; } @@ -113,20 +101,20 @@ __setup("relative_sleep_states=", sleep_states_setup); void suspend_set_ops(const struct platform_suspend_ops *ops) { suspend_state_t i; - int j = PM_SUSPEND_MAX - 1; + int j = 0; lock_system_sleep(); suspend_ops = ops; for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--) - if (valid_state(i)) - pm_states[j--].state = i; - else if (!relative_states) - pm_states[j--].state = 0; + if (valid_state(i)) { + pm_states[i] = pm_labels[j++]; + } else if (!relative_states) { + pm_states[i] = NULL; + j++; + } - pm_states[j--].state = PM_SUSPEND_FREEZE; - while (j >= PM_SUSPEND_MIN) - pm_states[j--].state = 0; + pm_states[PM_SUSPEND_FREEZE] = pm_labels[j]; unlock_system_sleep(); } @@ -145,6 +133,65 @@ int suspend_valid_only_mem(suspend_state_t state) } EXPORT_SYMBOL_GPL(suspend_valid_only_mem); +static bool sleep_state_supported(suspend_state_t state) +{ + return state == PM_SUSPEND_FREEZE || (suspend_ops && suspend_ops->enter); +} + +static int platform_suspend_prepare(suspend_state_t state) +{ + return state != PM_SUSPEND_FREEZE && suspend_ops->prepare ? + suspend_ops->prepare() : 0; +} + +static int platform_suspend_prepare_late(suspend_state_t state) +{ + return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ? + suspend_ops->prepare_late() : 0; +} + +static void platform_suspend_wake(suspend_state_t state) +{ + if (state != PM_SUSPEND_FREEZE && suspend_ops->wake) + suspend_ops->wake(); +} + +static void platform_suspend_finish(suspend_state_t state) +{ + if (state != PM_SUSPEND_FREEZE && suspend_ops->finish) + suspend_ops->finish(); +} + +static int platform_suspend_begin(suspend_state_t state) +{ + if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin) + return freeze_ops->begin(); + else if (suspend_ops->begin) + return suspend_ops->begin(state); + else + return 0; +} + +static void platform_suspend_end(suspend_state_t state) +{ + if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) + freeze_ops->end(); + else if (suspend_ops->end) + suspend_ops->end(); +} + +static void platform_suspend_recover(suspend_state_t state) +{ + if (state != PM_SUSPEND_FREEZE && suspend_ops->recover) + suspend_ops->recover(); +} + +static bool platform_suspend_again(suspend_state_t state) +{ + return state != PM_SUSPEND_FREEZE && suspend_ops->suspend_again ? + suspend_ops->suspend_again() : false; +} + static int suspend_test(int level) { #ifdef CONFIG_PM_DEBUG @@ -168,7 +215,7 @@ static int suspend_prepare(suspend_state_t state) { int error; - if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter)) + if (!sleep_state_supported(state)) return -EPERM; pm_prepare_console(); @@ -214,23 +261,18 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) { int error; - if (need_suspend_ops(state) && suspend_ops->prepare) { - error = suspend_ops->prepare(); - if (error) - goto Platform_finish; - } + error = platform_suspend_prepare(state); + if (error) + goto Platform_finish; error = dpm_suspend_end(PMSG_SUSPEND); if (error) { printk(KERN_ERR "PM: Some devices failed to power down\n"); goto Platform_finish; } - - if (need_suspend_ops(state) && suspend_ops->prepare_late) { - error = suspend_ops->prepare_late(); - if (error) - goto Platform_wake; - } + error = platform_suspend_prepare_late(state); + if (error) + goto Platform_wake; if (suspend_test(TEST_PLATFORM)) goto Platform_wake; @@ -276,15 +318,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) enable_nonboot_cpus(); Platform_wake: - if (need_suspend_ops(state) && suspend_ops->wake) - suspend_ops->wake(); - + platform_suspend_wake(state); dpm_resume_start(PMSG_RESUME); Platform_finish: - if (need_suspend_ops(state) && suspend_ops->finish) - suspend_ops->finish(); - + platform_suspend_finish(state); return error; } @@ -297,18 +335,13 @@ int suspend_devices_and_enter(suspend_state_t state) int error; bool wakeup = false; - if (need_suspend_ops(state) && !suspend_ops) + if (!sleep_state_supported(state)) return -ENOSYS; - if (need_suspend_ops(state) && suspend_ops->begin) { - error = suspend_ops->begin(state); - if (error) - goto Close; - } else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin) { - error = freeze_ops->begin(); - if (error) - goto Close; - } + error = platform_suspend_begin(state); + if (error) + goto Close; + suspend_console(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); @@ -322,25 +355,20 @@ int suspend_devices_and_enter(suspend_state_t state) do { error = suspend_enter(state, &wakeup); - } while (!error && !wakeup && need_suspend_ops(state) - && suspend_ops->suspend_again && suspend_ops->suspend_again()); + } while (!error && !wakeup && platform_suspend_again(state)); Resume_devices: suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); resume_console(); - Close: - if (need_suspend_ops(state) && suspend_ops->end) - suspend_ops->end(); - else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) - freeze_ops->end(); + Close: + platform_suspend_end(state); return error; Recover_platform: - if (need_suspend_ops(state) && suspend_ops->recover) - suspend_ops->recover(); + platform_suspend_recover(state); goto Resume_devices; } @@ -393,7 +421,7 @@ static int enter_state(suspend_state_t state) printk("done.\n"); trace_suspend_resume(TPS("sync_filesystems"), 0, false); - pr_debug("PM: Preparing system for %s sleep\n", pm_states[state].label); + pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(state); if (error) goto Unlock; @@ -402,7 +430,7 @@ static int enter_state(suspend_state_t state) goto Finish; trace_suspend_resume(TPS("suspend_enter"), state, false); - pr_debug("PM: Entering %s sleep\n", pm_states[state].label); + pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c index 269b097e78ea..2f524928b6aa 100644 --- a/kernel/power/suspend_test.c +++ b/kernel/power/suspend_test.c @@ -92,13 +92,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) } if (state == PM_SUSPEND_MEM) { - printk(info_test, pm_states[state].label); + printk(info_test, pm_states[state]); status = pm_suspend(state); if (status == -ENODEV) state = PM_SUSPEND_STANDBY; } if (state == PM_SUSPEND_STANDBY) { - printk(info_test, pm_states[state].label); + printk(info_test, pm_states[state]); status = pm_suspend(state); } if (status < 0) @@ -141,8 +141,8 @@ static int __init setup_test_suspend(char *value) /* "=mem" ==> "mem" */ value++; for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) - if (!strcmp(pm_states[i].label, value)) { - test_state = pm_states[i].state; + if (!strcmp(pm_states[i], value)) { + test_state = i; return 0; } @@ -162,8 +162,8 @@ static int __init test_suspend(void) /* PM is initialized by now; is that state testable? */ if (test_state == PM_SUSPEND_ON) goto done; - if (!pm_states[test_state].state) { - printk(warn_bad_state, pm_states[test_state].label); + if (!pm_states[test_state]) { + printk(warn_bad_state, pm_states[test_state]); goto done; } diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 9f1608f99819..11e7bc434f43 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -147,8 +147,6 @@ use_default: clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu)) goto use_default; - trace_cpu_idle_rcuidle(next_state, dev->cpu); - /* * Enter the idle state previously returned by the governor decision. * This function will block until an interrupt occurs and will take @@ -156,8 +154,6 @@ use_default: */ entered_state = cpuidle_enter(drv, dev, next_state); - trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); - if (broadcast) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index e5a3c4be2a10..3d1537b93c64 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -108,13 +108,18 @@ DUMP_OBJS = \ apmain.o\ osunixdir.o\ osunixmap.o\ + osunixxf.o\ tbprint.o\ tbxfroot.o\ utbuffer.o\ + utdebug.o\ utexcep.o\ + utglobal.o\ utmath.o\ + utprint.o\ utstring.o\ utxferror.o\ + oslibcfs.o\ oslinuxtbl.o\ cmfsize.o\ getopt.o diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c index 5140e5edae1f..f4b953354ff7 100644 --- a/tools/power/acpi/common/cmfsize.c +++ b/tools/power/acpi/common/cmfsize.c @@ -58,44 +58,46 @@ ACPI_MODULE_NAME("cmfsize") * RETURN: File Size. On error, -1 (ACPI_UINT32_MAX) * * DESCRIPTION: Get the size of a file. Uses seek-to-EOF. File must be open. - * Does not disturb the current file pointer. Uses perror for - * error messages. + * Does not disturb the current file pointer. * ******************************************************************************/ -u32 cm_get_file_size(FILE * file) +u32 cm_get_file_size(ACPI_FILE file) { long file_size; long current_offset; + acpi_status status; /* Save the current file pointer, seek to EOF to obtain file size */ - current_offset = ftell(file); + current_offset = acpi_os_get_file_offset(file); if (current_offset < 0) { goto offset_error; } - if (fseek(file, 0, SEEK_END)) { + status = acpi_os_set_file_offset(file, 0, ACPI_FILE_END); + if (ACPI_FAILURE(status)) { goto seek_error; } - file_size = ftell(file); + file_size = acpi_os_get_file_offset(file); if (file_size < 0) { goto offset_error; } /* Restore original file pointer */ - if (fseek(file, current_offset, SEEK_SET)) { + status = acpi_os_set_file_offset(file, current_offset, ACPI_FILE_BEGIN); + if (ACPI_FAILURE(status)) { goto seek_error; } return ((u32)file_size); offset_error: - perror("Could not get file offset"); + acpi_log_error("Could not get file offset"); return (ACPI_UINT32_MAX); seek_error: - perror("Could not seek file"); + acpi_log_error("Could not set file offset"); return (ACPI_UINT32_MAX); } diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c index a302f52e4fd3..2f0f34a36db4 100644 --- a/tools/power/acpi/common/getopt.c +++ b/tools/power/acpi/common/getopt.c @@ -51,14 +51,12 @@ * "f|" - Option has required single-char sub-options */ -#include <stdio.h> -#include <string.h> #include <acpi/acpi.h> #include "accommon.h" #include "acapps.h" #define ACPI_OPTION_ERROR(msg, badchar) \ - if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} + if (acpi_gbl_opterr) {acpi_log_error ("%s%c\n", msg, badchar);} int acpi_gbl_opterr = 1; int acpi_gbl_optind = 1; @@ -113,7 +111,7 @@ int acpi_getopt_argument(int argc, char **argv) * PARAMETERS: argc, argv - from main * opts - options info list * - * RETURN: Option character or EOF + * RETURN: Option character or ACPI_OPT_END * * DESCRIPTION: Get the next option * @@ -128,10 +126,10 @@ int acpi_getopt(int argc, char **argv, char *opts) if (acpi_gbl_optind >= argc || argv[acpi_gbl_optind][0] != '-' || argv[acpi_gbl_optind][1] == '\0') { - return (EOF); - } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { + return (ACPI_OPT_END); + } else if (ACPI_STRCMP(argv[acpi_gbl_optind], "--") == 0) { acpi_gbl_optind++; - return (EOF); + return (ACPI_OPT_END); } } @@ -142,7 +140,7 @@ int acpi_getopt(int argc, char **argv, char *opts) /* Make sure that the option is legal */ if (current_char == ':' || - (opts_ptr = strchr(opts, current_char)) == NULL) { + (opts_ptr = ACPI_STRCHR(opts, current_char)) == NULL) { ACPI_OPTION_ERROR("Illegal option: -", current_char); if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { diff --git a/tools/power/acpi/os_specific/service_layers/oslibcfs.c b/tools/power/acpi/os_specific/service_layers/oslibcfs.c new file mode 100644 index 000000000000..c13ff9c51d74 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/oslibcfs.c @@ -0,0 +1,214 @@ +/****************************************************************************** + * + * Module Name: oslibcfs - C library OSL for file I/O + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include <stdio.h> +#include <stdarg.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("oslibcfs") + +/******************************************************************************* + * + * FUNCTION: acpi_os_open_file + * + * PARAMETERS: path - File path + * modes - File operation type + * + * RETURN: File descriptor. + * + * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing + * (ACPI_FILE_WRITING). + * + ******************************************************************************/ +ACPI_FILE acpi_os_open_file(const char *path, u8 modes) +{ + ACPI_FILE file; + u32 i = 0; + char modes_str[4]; + + if (modes & ACPI_FILE_READING) { + modes_str[i++] = 'r'; + } + if (modes & ACPI_FILE_WRITING) { + modes_str[i++] = 'w'; + } + if (modes & ACPI_FILE_BINARY) { + modes_str[i++] = 'b'; + } + + modes_str[i++] = '\0'; + + file = fopen(path, modes_str); + if (!file) { + perror("Could not open file"); + } + + return (file); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_close_file + * + * PARAMETERS: file - An open file descriptor + * + * RETURN: None. + * + * DESCRIPTION: Close a file opened via acpi_os_open_file. + * + ******************************************************************************/ + +void acpi_os_close_file(ACPI_FILE file) +{ + fclose(file); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_read_file + * + * PARAMETERS: file - An open file descriptor + * buffer - Data buffer + * size - Data block size + * count - Number of data blocks + * + * RETURN: Number of bytes actually read. + * + * DESCRIPTION: Read from a file. + * + ******************************************************************************/ + +int +acpi_os_read_file(ACPI_FILE file, void *buffer, acpi_size size, acpi_size count) +{ + int length; + + length = fread(buffer, size, count, file); + if (length < 0) { + perror("Error reading file"); + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_write_file + * + * PARAMETERS: file - An open file descriptor + * buffer - Data buffer + * size - Data block size + * count - Number of data blocks + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Write to a file. + * + ******************************************************************************/ + +int +acpi_os_write_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count) +{ + int length; + + length = fwrite(buffer, size, count, file); + if (length < 0) { + perror("Error writing file"); + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_get_file_offset + * + * PARAMETERS: file - An open file descriptor + * + * RETURN: Current file pointer position. + * + * DESCRIPTION: Get current file offset. + * + ******************************************************************************/ + +long acpi_os_get_file_offset(ACPI_FILE file) +{ + long offset; + + offset = ftell(file); + return (offset); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_set_file_offset + * + * PARAMETERS: file - An open file descriptor + * offset - New file offset + * from - From begin/end of file + * + * RETURN: Status + * + * DESCRIPTION: Set current file offset. + * + ******************************************************************************/ + +acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from) +{ + int ret = 0; + + if (from == ACPI_FILE_BEGIN) { + ret = fseek(file, offset, SEEK_SET); + } + if (from == ACPI_FILE_END) { + ret = fseek(file, offset, SEEK_END); + } + + if (ret < 0) { + return (AE_ERROR); + } else { + return (AE_OK); + } +} diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c index 28c52008e854..0dc2485dedf5 100644 --- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c +++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c @@ -77,6 +77,9 @@ osl_map_table(acpi_size address, static void osl_unmap_table(struct acpi_table_header *table); +static acpi_physical_address +osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword); + static acpi_physical_address osl_find_rsdp_via_efi(void); static acpi_status osl_load_rsdp(void); @@ -417,6 +420,38 @@ acpi_os_get_table_by_index(u32 index, /****************************************************************************** * + * FUNCTION: osl_find_rsdp_via_efi_by_keyword + * + * PARAMETERS: keyword - Character string indicating ACPI GUID version + * in the EFI table + * + * RETURN: RSDP address if found + * + * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI + * GUID version. + * + *****************************************************************************/ + +static acpi_physical_address +osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword) +{ + char buffer[80]; + unsigned long long address = 0; + char format[32]; + + snprintf(format, 32, "%s=%s", keyword, "%llx"); + fseek(file, 0, SEEK_SET); + while (fgets(buffer, 80, file)) { + if (sscanf(buffer, format, &address) == 1) { + break; + } + } + + return ((acpi_physical_address) (address)); +} + +/****************************************************************************** + * * FUNCTION: osl_find_rsdp_via_efi * * PARAMETERS: None @@ -430,20 +465,19 @@ acpi_os_get_table_by_index(u32 index, static acpi_physical_address osl_find_rsdp_via_efi(void) { FILE *file; - char buffer[80]; - unsigned long address = 0; + acpi_physical_address address = 0; file = fopen(EFI_SYSTAB, "r"); if (file) { - while (fgets(buffer, 80, file)) { - if (sscanf(buffer, "ACPI20=0x%lx", &address) == 1) { - break; - } + address = osl_find_rsdp_via_efi_by_keyword(file, "ACPI20"); + if (!address) { + address = + osl_find_rsdp_via_efi_by_keyword(file, "ACPI"); } fclose(file); } - return ((acpi_physical_address) (address)); + return (address); } /****************************************************************************** diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c new file mode 100644 index 000000000000..60b58cd18410 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c @@ -0,0 +1,1311 @@ +/****************************************************************************** + * + * Module Name: osunixxf - UNIX OSL interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These interfaces are required in order to compile the ASL compiler and the + * various ACPICA tools under Linux or other Unix-like system. + */ +#include <acpi/acpi.h> +#include "accommon.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdebug.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <sys/time.h> +#include <semaphore.h> +#include <pthread.h> +#include <errno.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("osunixxf") + +u8 acpi_gbl_debug_timeout = FALSE; + +/* Upcalls to acpi_exec */ + +void +ae_table_override(struct acpi_table_header *existing_table, + struct acpi_table_header **new_table); + +typedef void *(*PTHREAD_CALLBACK) (void *); + +/* Buffer used by acpi_os_vprintf */ + +#define ACPI_VPRINTF_BUFFER_SIZE 512 +#define _ASCII_NEWLINE '\n' + +/* Terminal support for acpi_exec only */ + +#ifdef ACPI_EXEC_APP +#include <termios.h> + +struct termios original_term_attributes; +int term_attributes_were_set = 0; + +acpi_status acpi_ut_read_line(char *buffer, u32 buffer_length, u32 *bytes_read); + +static void os_enter_line_edit_mode(void); + +static void os_exit_line_edit_mode(void); + +/****************************************************************************** + * + * FUNCTION: os_enter_line_edit_mode, os_exit_line_edit_mode + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enter/Exit the raw character input mode for the terminal. + * + * Interactive line-editing support for the AML debugger. Used with the + * common/acgetline module. + * + * readline() is not used because of non-portability. It is not available + * on all systems, and if it is, often the package must be manually installed. + * + * Therefore, we use the POSIX tcgetattr/tcsetattr and do the minimal line + * editing that we need in acpi_os_get_line. + * + * If the POSIX tcgetattr/tcsetattr interfaces are unavailable, these + * calls will also work: + * For os_enter_line_edit_mode: system ("stty cbreak -echo") + * For os_exit_line_edit_mode: system ("stty cooked echo") + * + *****************************************************************************/ + +static void os_enter_line_edit_mode(void) +{ + struct termios local_term_attributes; + + /* Get and keep the original attributes */ + + if (tcgetattr(STDIN_FILENO, &original_term_attributes)) { + fprintf(stderr, "Could not get terminal attributes!\n"); + return; + } + + /* Set the new attributes to enable raw character input */ + + memcpy(&local_term_attributes, &original_term_attributes, + sizeof(struct termios)); + + local_term_attributes.c_lflag &= ~(ICANON | ECHO); + local_term_attributes.c_cc[VMIN] = 1; + local_term_attributes.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FILENO, TCSANOW, &local_term_attributes)) { + fprintf(stderr, "Could not set terminal attributes!\n"); + return; + } + + term_attributes_were_set = 1; +} + +static void os_exit_line_edit_mode(void) +{ + + if (!term_attributes_were_set) { + return; + } + + /* Set terminal attributes back to the original values */ + + if (tcsetattr(STDIN_FILENO, TCSANOW, &original_term_attributes)) { + fprintf(stderr, "Could not restore terminal attributes!\n"); + } +} + +#else + +/* These functions are not needed for other ACPICA utilities */ + +#define os_enter_line_edit_mode() +#define os_exit_line_edit_mode() +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_initialize, acpi_os_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and terminate this module. + * + *****************************************************************************/ + +acpi_status acpi_os_initialize(void) +{ + acpi_status status; + + acpi_gbl_output_file = stdout; + + os_enter_line_edit_mode(); + + status = acpi_os_create_lock(&acpi_gbl_print_lock); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (AE_OK); +} + +acpi_status acpi_os_terminate(void) +{ + + os_exit_line_edit_mode(); + return (AE_OK); +} + +#ifndef ACPI_USE_NATIVE_RSDP_POINTER +/****************************************************************************** + * + * FUNCTION: acpi_os_get_root_pointer + * + * PARAMETERS: None + * + * RETURN: RSDP physical address + * + * DESCRIPTION: Gets the ACPI root pointer (RSDP) + * + *****************************************************************************/ + +acpi_physical_address acpi_os_get_root_pointer(void) +{ + + return (0); +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_predefined_override + * + * PARAMETERS: init_val - Initial value of the predefined object + * new_val - The new value for the object + * + * RETURN: Status, pointer to value. Null pointer returned if not + * overriding. + * + * DESCRIPTION: Allow the OS to override predefined names + * + *****************************************************************************/ + +acpi_status +acpi_os_predefined_override(const struct acpi_predefined_names * init_val, + acpi_string * new_val) +{ + + if (!init_val || !new_val) { + return (AE_BAD_PARAMETER); + } + + *new_val = NULL; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_table_override + * + * PARAMETERS: existing_table - Header of current table (probably + * firmware) + * new_table - Where an entire new table is returned. + * + * RETURN: Status, pointer to new table. Null pointer returned if no + * table is available to override + * + * DESCRIPTION: Return a different version of a table if one is available + * + *****************************************************************************/ + +acpi_status +acpi_os_table_override(struct acpi_table_header * existing_table, + struct acpi_table_header ** new_table) +{ + + if (!existing_table || !new_table) { + return (AE_BAD_PARAMETER); + } + + *new_table = NULL; + +#ifdef ACPI_EXEC_APP + + ae_table_override(existing_table, new_table); + return (AE_OK); +#else + + return (AE_NO_ACPI_TABLES); +#endif +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_physical_table_override + * + * PARAMETERS: existing_table - Header of current table (probably firmware) + * new_address - Where new table address is returned + * (Physical address) + * new_table_length - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +acpi_status +acpi_os_physical_table_override(struct acpi_table_header * existing_table, + acpi_physical_address * new_address, + u32 *new_table_length) +{ + + return (AE_SUPPORT); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_redirect_output + * + * PARAMETERS: destination - An open file handle/pointer + * + * RETURN: None + * + * DESCRIPTION: Causes redirect of acpi_os_printf and acpi_os_vprintf + * + *****************************************************************************/ + +void acpi_os_redirect_output(void *destination) +{ + + acpi_gbl_output_file = destination; +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_printf + * + * PARAMETERS: fmt, ... - Standard printf format + * + * RETURN: None + * + * DESCRIPTION: Formatted output. Note: very similar to acpi_os_vprintf + * (performance), changes should be tracked in both functions. + * + *****************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) +{ + va_list args; + u8 flags; + + flags = acpi_gbl_db_output_flags; + if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { + + /* Output is directable to either a file (if open) or the console */ + + if (acpi_gbl_debug_file) { + + /* Output file is open, send the output there */ + + va_start(args, fmt); + vfprintf(acpi_gbl_debug_file, fmt, args); + va_end(args); + } else { + /* No redirection, send output to console (once only!) */ + + flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (flags & ACPI_DB_CONSOLE_OUTPUT) { + va_start(args, fmt); + vfprintf(acpi_gbl_output_file, fmt, args); + va_end(args); + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_vprintf + * + * PARAMETERS: fmt - Standard printf format + * args - Argument list + * + * RETURN: None + * + * DESCRIPTION: Formatted output with argument list pointer. Note: very + * similar to acpi_os_printf, changes should be tracked in both + * functions. + * + *****************************************************************************/ + +void acpi_os_vprintf(const char *fmt, va_list args) +{ + u8 flags; + char buffer[ACPI_VPRINTF_BUFFER_SIZE]; + + /* + * We build the output string in a local buffer because we may be + * outputting the buffer twice. Using vfprintf is problematic because + * some implementations modify the args pointer/structure during + * execution. Thus, we use the local buffer for portability. + * + * Note: Since this module is intended for use by the various ACPICA + * utilities/applications, we can safely declare the buffer on the stack. + * Also, This function is used for relatively small error messages only. + */ + vsnprintf(buffer, ACPI_VPRINTF_BUFFER_SIZE, fmt, args); + + flags = acpi_gbl_db_output_flags; + if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { + + /* Output is directable to either a file (if open) or the console */ + + if (acpi_gbl_debug_file) { + + /* Output file is open, send the output there */ + + fputs(buffer, acpi_gbl_debug_file); + } else { + /* No redirection, send output to console (once only!) */ + + flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (flags & ACPI_DB_CONSOLE_OUTPUT) { + fputs(buffer, acpi_gbl_output_file); + } +} + +#ifndef ACPI_EXEC_APP +/****************************************************************************** + * + * FUNCTION: acpi_os_get_line + * + * PARAMETERS: buffer - Where to return the command line + * buffer_length - Maximum length of Buffer + * bytes_read - Where the actual byte count is returned + * + * RETURN: Status and actual bytes read + * + * DESCRIPTION: Get the next input line from the terminal. NOTE: For the + * acpi_exec utility, we use the acgetline module instead to + * provide line-editing and history support. + * + *****************************************************************************/ + +acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) +{ + int input_char; + u32 end_of_line; + + /* Standard acpi_os_get_line for all utilities except acpi_exec */ + + for (end_of_line = 0;; end_of_line++) { + if (end_of_line >= buffer_length) { + return (AE_BUFFER_OVERFLOW); + } + + if ((input_char = getchar()) == EOF) { + return (AE_ERROR); + } + + if (!input_char || input_char == _ASCII_NEWLINE) { + break; + } + + buffer[end_of_line] = (char)input_char; + } + + /* Null terminate the buffer */ + + buffer[end_of_line] = 0; + + /* Return the number of bytes in the string */ + + if (bytes_read) { + *bytes_read = end_of_line; + } + + return (AE_OK); +} +#endif + +#ifndef ACPI_USE_NATIVE_MEMORY_MAPPING +/****************************************************************************** + * + * FUNCTION: acpi_os_map_memory + * + * PARAMETERS: where - Physical address of memory to be mapped + * length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into caller's address space + * + *****************************************************************************/ + +void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) +{ + + return (ACPI_TO_POINTER((acpi_size) where)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_unmap_memory + * + * PARAMETERS: where - Logical address of memory to be unmapped + * length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void acpi_os_unmap_memory(void *where, acpi_size length) +{ + + return; +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_allocate + * + * PARAMETERS: size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void *acpi_os_allocate(acpi_size size) +{ + void *mem; + + mem = (void *)malloc((size_t) size); + return (mem); +} + +#ifdef USE_NATIVE_ALLOCATE_ZEROED +/****************************************************************************** + * + * FUNCTION: acpi_os_allocate_zeroed + * + * PARAMETERS: size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void *acpi_os_allocate_zeroed(acpi_size size) +{ + void *mem; + + mem = (void *)calloc(1, (size_t) size); + return (mem); +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_free + * + * PARAMETERS: mem - Pointer to previously allocated memory + * + * RETURN: None. + * + * DESCRIPTION: Free memory allocated via acpi_os_allocate + * + *****************************************************************************/ + +void acpi_os_free(void *mem) +{ + + free(mem); +} + +#ifdef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: Semaphore stub functions + * + * DESCRIPTION: Stub functions used for single-thread applications that do + * not require semaphore synchronization. Full implementations + * of these functions appear after the stubs. + * + *****************************************************************************/ + +acpi_status +acpi_os_create_semaphore(u32 max_units, + u32 initial_units, acpi_handle * out_handle) +{ + *out_handle = (acpi_handle) 1; + return (AE_OK); +} + +acpi_status acpi_os_delete_semaphore(acpi_handle handle) +{ + return (AE_OK); +} + +acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) +{ + return (AE_OK); +} + +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) +{ + return (AE_OK); +} + +#else +/****************************************************************************** + * + * FUNCTION: acpi_os_create_semaphore + * + * PARAMETERS: initial_units - Units to be assigned to the new semaphore + * out_handle - Where a handle will be returned + * + * RETURN: Status + * + * DESCRIPTION: Create an OS semaphore + * + *****************************************************************************/ + +acpi_status +acpi_os_create_semaphore(u32 max_units, + u32 initial_units, acpi_handle * out_handle) +{ + sem_t *sem; + + if (!out_handle) { + return (AE_BAD_PARAMETER); + } +#ifdef __APPLE__ + { + char *semaphore_name = tmpnam(NULL); + + sem = + sem_open(semaphore_name, O_EXCL | O_CREAT, 0755, + initial_units); + if (!sem) { + return (AE_NO_MEMORY); + } + sem_unlink(semaphore_name); /* This just deletes the name */ + } + +#else + sem = acpi_os_allocate(sizeof(sem_t)); + if (!sem) { + return (AE_NO_MEMORY); + } + + if (sem_init(sem, 0, initial_units) == -1) { + acpi_os_free(sem); + return (AE_BAD_PARAMETER); + } +#endif + + *out_handle = (acpi_handle) sem; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_delete_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * + * RETURN: Status + * + * DESCRIPTION: Delete an OS semaphore + * + *****************************************************************************/ + +acpi_status acpi_os_delete_semaphore(acpi_handle handle) +{ + sem_t *sem = (sem_t *) handle; + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + if (sem_destroy(sem) == -1) { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_wait_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * units - How many units to wait for + * msec_timeout - How long to wait (milliseconds) + * + * RETURN: Status + * + * DESCRIPTION: Wait for units + * + *****************************************************************************/ + +acpi_status +acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout) +{ + acpi_status status = AE_OK; + sem_t *sem = (sem_t *) handle; +#ifndef ACPI_USE_ALTERNATE_TIMEOUT + struct timespec time; + int ret_val; +#endif + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + switch (msec_timeout) { + /* + * No Wait: + * -------- + * A zero timeout value indicates that we shouldn't wait - just + * acquire the semaphore if available otherwise return AE_TIME + * (a.k.a. 'would block'). + */ + case 0: + + if (sem_trywait(sem) == -1) { + status = (AE_TIME); + } + break; + + /* Wait Indefinitely */ + + case ACPI_WAIT_FOREVER: + + if (sem_wait(sem)) { + status = (AE_TIME); + } + break; + + /* Wait with msec_timeout */ + + default: + +#ifdef ACPI_USE_ALTERNATE_TIMEOUT + /* + * Alternate timeout mechanism for environments where + * sem_timedwait is not available or does not work properly. + */ + while (msec_timeout) { + if (sem_trywait(sem) == 0) { + + /* Got the semaphore */ + return (AE_OK); + } + + if (msec_timeout >= 10) { + msec_timeout -= 10; + usleep(10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */ + } else { + msec_timeout--; + usleep(ACPI_USEC_PER_MSEC); /* one millisecond */ + } + } + status = (AE_TIME); +#else + /* + * The interface to sem_timedwait is an absolute time, so we need to + * get the current time, then add in the millisecond Timeout value. + */ + if (clock_gettime(CLOCK_REALTIME, &time) == -1) { + perror("clock_gettime"); + return (AE_TIME); + } + + time.tv_sec += (msec_timeout / ACPI_MSEC_PER_SEC); + time.tv_nsec += + ((msec_timeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC); + + /* Handle nanosecond overflow (field must be less than one second) */ + + if (time.tv_nsec >= ACPI_NSEC_PER_SEC) { + time.tv_sec += (time.tv_nsec / ACPI_NSEC_PER_SEC); + time.tv_nsec = (time.tv_nsec % ACPI_NSEC_PER_SEC); + } + + while (((ret_val = sem_timedwait(sem, &time)) == -1) + && (errno == EINTR)) { + continue; + } + + if (ret_val != 0) { + if (errno != ETIMEDOUT) { + perror("sem_timedwait"); + } + status = (AE_TIME); + } +#endif + break; + } + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_signal_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * units - Number of units to send + * + * RETURN: Status + * + * DESCRIPTION: Send units + * + *****************************************************************************/ + +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) +{ + sem_t *sem = (sem_t *) handle; + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + if (sem_post(sem) == -1) { + return (AE_LIMIT); + } + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + +/****************************************************************************** + * + * FUNCTION: Spinlock interfaces + * + * DESCRIPTION: Map these interfaces to semaphore interfaces + * + *****************************************************************************/ + +acpi_status acpi_os_create_lock(acpi_spinlock * out_handle) +{ + + return (acpi_os_create_semaphore(1, 1, out_handle)); +} + +void acpi_os_delete_lock(acpi_spinlock handle) +{ + acpi_os_delete_semaphore(handle); +} + +acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle) +{ + acpi_os_wait_semaphore(handle, 1, 0xFFFF); + return (0); +} + +void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags) +{ + acpi_os_signal_semaphore(handle, 1); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_install_interrupt_handler + * + * PARAMETERS: interrupt_number - Level handler should respond to. + * isr - Address of the ACPI interrupt handler + * except_ptr - Where status is returned + * + * RETURN: Handle to the newly installed handler. + * + * DESCRIPTION: Install an interrupt handler. Used to install the ACPI + * OS-independent handler. + * + *****************************************************************************/ + +u32 +acpi_os_install_interrupt_handler(u32 interrupt_number, + acpi_osd_handler service_routine, + void *context) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_remove_interrupt_handler + * + * PARAMETERS: handle - Returned when handler was installed + * + * RETURN: Status + * + * DESCRIPTION: Uninstalls an interrupt handler. + * + *****************************************************************************/ + +acpi_status +acpi_os_remove_interrupt_handler(u32 interrupt_number, + acpi_osd_handler service_routine) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_stall + * + * PARAMETERS: microseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at microsecond granularity + * + *****************************************************************************/ + +void acpi_os_stall(u32 microseconds) +{ + + if (microseconds) { + usleep(microseconds); + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_sleep + * + * PARAMETERS: milliseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at millisecond granularity + * + *****************************************************************************/ + +void acpi_os_sleep(u64 milliseconds) +{ + + /* Sleep for whole seconds */ + + sleep(milliseconds / ACPI_MSEC_PER_SEC); + + /* + * Sleep for remaining microseconds. + * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second). + */ + usleep((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_get_timer + * + * PARAMETERS: None + * + * RETURN: Current time in 100 nanosecond units + * + * DESCRIPTION: Get the current system time + * + *****************************************************************************/ + +u64 acpi_os_get_timer(void) +{ + struct timeval time; + + /* This timer has sufficient resolution for user-space application code */ + + gettimeofday(&time, NULL); + + /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */ + + return (((u64)time.tv_sec * ACPI_100NSEC_PER_SEC) + + ((u64)time.tv_usec * ACPI_100NSEC_PER_USEC)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_pci_configuration + * + * PARAMETERS: pci_id - Seg/Bus/Dev + * pci_register - Device Register + * value - Buffer where value is placed + * width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Read data from PCI configuration space + * + *****************************************************************************/ + +acpi_status +acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, + u32 pci_register, u64 *value, u32 width) +{ + + *value = 0; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_pci_configuration + * + * PARAMETERS: pci_id - Seg/Bus/Dev + * pci_register - Device Register + * value - Value to be written + * width - Number of bits + * + * RETURN: Status. + * + * DESCRIPTION: Write data to PCI configuration space + * + *****************************************************************************/ + +acpi_status +acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, + u32 pci_register, u64 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_port + * + * PARAMETERS: address - Address of I/O port/register to read + * value - Where value is placed + * width - Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register + * + *****************************************************************************/ + +acpi_status acpi_os_read_port(acpi_io_address address, u32 *value, u32 width) +{ + + switch (width) { + case 8: + + *value = 0xFF; + break; + + case 16: + + *value = 0xFFFF; + break; + + case 32: + + *value = 0xFFFFFFFF; + break; + + default: + + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_port + * + * PARAMETERS: address - Address of I/O port/register to write + * value - Value to write + * width - Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register + * + *****************************************************************************/ + +acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_memory + * + * PARAMETERS: address - Physical Memory Address to read + * value - Where value is placed + * width - Number of bits (8,16,32, or 64) + * + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. + * + * DESCRIPTION: Read data from a physical memory address + * + *****************************************************************************/ + +acpi_status +acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width) +{ + + switch (width) { + case 8: + case 16: + case 32: + case 64: + + *value = 0; + break; + + default: + + return (AE_BAD_PARAMETER); + } + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_memory + * + * PARAMETERS: address - Physical Memory Address to write + * value - Value to write + * width - Number of bits (8,16,32, or 64) + * + * RETURN: None + * + * DESCRIPTION: Write data to a physical memory address + * + *****************************************************************************/ + +acpi_status +acpi_os_write_memory(acpi_physical_address address, u64 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_readable + * + * PARAMETERS: pointer - Area to be verified + * length - Size of area + * + * RETURN: TRUE if readable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for reading + * + *****************************************************************************/ + +u8 acpi_os_readable(void *pointer, acpi_size length) +{ + + return (TRUE); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_writable + * + * PARAMETERS: pointer - Area to be verified + * length - Size of area + * + * RETURN: TRUE if writable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for writing + * + *****************************************************************************/ + +u8 acpi_os_writable(void *pointer, acpi_size length) +{ + + return (TRUE); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_signal + * + * PARAMETERS: function - ACPI A signal function code + * info - Pointer to function-dependent structure + * + * RETURN: Status + * + * DESCRIPTION: Miscellaneous functions. Example implementation only. + * + *****************************************************************************/ + +acpi_status acpi_os_signal(u32 function, void *info) +{ + + switch (function) { + case ACPI_SIGNAL_FATAL: + + break; + + case ACPI_SIGNAL_BREAKPOINT: + + break; + + default: + + break; + } + + return (AE_OK); +} + +/* Optional multi-thread support */ + +#ifndef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: acpi_os_get_thread_id + * + * PARAMETERS: None + * + * RETURN: Id of the running thread + * + * DESCRIPTION: Get the ID of the current (running) thread + * + *****************************************************************************/ + +acpi_thread_id acpi_os_get_thread_id(void) +{ + pthread_t thread; + + thread = pthread_self(); + return (ACPI_CAST_PTHREAD_T(thread)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_execute + * + * PARAMETERS: type - Type of execution + * function - Address of the function to execute + * context - Passed as a parameter to the function + * + * RETURN: Status. + * + * DESCRIPTION: Execute a new thread + * + *****************************************************************************/ + +acpi_status +acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + pthread_t thread; + int ret; + + ret = + pthread_create(&thread, NULL, (PTHREAD_CALLBACK) function, context); + if (ret) { + acpi_os_printf("Create thread failed"); + } + return (0); +} + +#else /* ACPI_SINGLE_THREADED */ +acpi_thread_id acpi_os_get_thread_id(void) +{ + return (1); +} + +acpi_status +acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + + function(context); + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + +/****************************************************************************** + * + * FUNCTION: acpi_os_wait_events_complete + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Wait for all asynchronous events to complete. This + * implementation does nothing. + * + *****************************************************************************/ + +void acpi_os_wait_events_complete(void) +{ + return; +} diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h index 46f519597fe5..a2d37d610639 100644 --- a/tools/power/acpi/tools/acpidump/acpidump.h +++ b/tools/power/acpi/tools/acpidump/acpidump.h @@ -47,7 +47,6 @@ #ifdef _DECLARE_GLOBALS #define EXTERN #define INIT_GLOBAL(a,b) a=b -#define DEFINE_ACPI_GLOBALS 1 #else #define EXTERN extern #define INIT_GLOBAL(a,b) a @@ -69,7 +68,7 @@ EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE); EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE); EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, FALSE); EXTERN u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, FALSE); -EXTERN FILE INIT_GLOBAL(*gbl_output_file, NULL); +EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL); EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c index 3cac12378366..53cee781e24e 100644 --- a/tools/power/acpi/tools/acpidump/apdump.c +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -69,17 +69,16 @@ u8 ap_is_valid_header(struct acpi_table_header *table) /* Make sure signature is all ASCII and a valid ACPI name */ if (!acpi_ut_valid_acpi_name(table->signature)) { - fprintf(stderr, - "Table signature (0x%8.8X) is invalid\n", - *(u32 *)table->signature); + acpi_log_error("Table signature (0x%8.8X) is invalid\n", + *(u32 *)table->signature); return (FALSE); } /* Check for minimum table length */ if (table->length < sizeof(struct acpi_table_header)) { - fprintf(stderr, "Table length (0x%8.8X) is invalid\n", - table->length); + acpi_log_error("Table length (0x%8.8X) is invalid\n", + table->length); return (FALSE); } } @@ -116,8 +115,8 @@ u8 ap_is_valid_checksum(struct acpi_table_header *table) } if (ACPI_FAILURE(status)) { - fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", - table->signature); + acpi_log_error("%4.4s: Warning: wrong checksum in table\n", + table->signature); } return (AE_OK); @@ -196,12 +195,13 @@ ap_dump_table_buffer(struct acpi_table_header *table, * Note: simplest to just always emit a 64-bit address. acpi_xtract * utility can handle this. */ - printf("%4.4s @ 0x%8.8X%8.8X\n", table->signature, - ACPI_FORMAT_UINT64(address)); + acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n", + table->signature, ACPI_FORMAT_UINT64(address)); - acpi_ut_dump_buffer(ACPI_CAST_PTR(u8, table), table_length, - DB_BYTE_DISPLAY, 0); - printf("\n"); + acpi_ut_dump_buffer_to_file(gbl_output_file, + ACPI_CAST_PTR(u8, table), table_length, + DB_BYTE_DISPLAY, 0); + acpi_ut_file_printf(gbl_output_file, "\n"); return (0); } @@ -239,20 +239,20 @@ int ap_dump_all_tables(void) if (status == AE_LIMIT) { return (0); } else if (i == 0) { - fprintf(stderr, - "Could not get ACPI tables, %s\n", - acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI tables, %s\n", + acpi_format_exception(status)); return (-1); } else { - fprintf(stderr, - "Could not get ACPI table at index %u, %s\n", - i, acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI table at index %u, %s\n", + i, acpi_format_exception(status)); continue; } } table_status = ap_dump_table_buffer(table, instance, address); - free(table); + ACPI_FREE(table); if (table_status) { break; @@ -288,22 +288,22 @@ int ap_dump_table_by_address(char *ascii_address) status = acpi_ut_strtoul64(ascii_address, 0, &long_address); if (ACPI_FAILURE(status)) { - fprintf(stderr, "%s: Could not convert to a physical address\n", - ascii_address); + acpi_log_error("%s: Could not convert to a physical address\n", + ascii_address); return (-1); } address = (acpi_physical_address) long_address; status = acpi_os_get_table_by_address(address, &table); if (ACPI_FAILURE(status)) { - fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n", - ACPI_FORMAT_UINT64(address), - acpi_format_exception(status)); + acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", + ACPI_FORMAT_UINT64(address), + acpi_format_exception(status)); return (-1); } table_status = ap_dump_table_buffer(table, 0, address); - free(table); + ACPI_FREE(table); return (table_status); } @@ -329,24 +329,24 @@ int ap_dump_table_by_name(char *signature) acpi_status status; int table_status; - if (strlen(signature) != ACPI_NAME_SIZE) { - fprintf(stderr, - "Invalid table signature [%s]: must be exactly 4 characters\n", - signature); + if (ACPI_STRLEN(signature) != ACPI_NAME_SIZE) { + acpi_log_error + ("Invalid table signature [%s]: must be exactly 4 characters\n", + signature); return (-1); } /* Table signatures are expected to be uppercase */ - strcpy(local_signature, signature); + ACPI_STRCPY(local_signature, signature); acpi_ut_strupr(local_signature); /* To be friendly, handle tables whose signatures do not match the name */ if (ACPI_COMPARE_NAME(local_signature, "FADT")) { - strcpy(local_signature, ACPI_SIG_FADT); + ACPI_STRCPY(local_signature, ACPI_SIG_FADT); } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) { - strcpy(local_signature, ACPI_SIG_MADT); + ACPI_STRCPY(local_signature, ACPI_SIG_MADT); } /* Dump all instances of this signature (to handle multiple SSDTs) */ @@ -362,14 +362,14 @@ int ap_dump_table_by_name(char *signature) return (0); } - fprintf(stderr, - "Could not get ACPI table with signature [%s], %s\n", - local_signature, acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI table with signature [%s], %s\n", + local_signature, acpi_format_exception(status)); return (-1); } table_status = ap_dump_table_buffer(table, instance, address); - free(table); + ACPI_FREE(table); if (table_status) { break; @@ -409,43 +409,21 @@ int ap_dump_table_from_file(char *pathname) /* File must be at least as long as the table length */ if (table->length > file_size) { - fprintf(stderr, - "Table length (0x%X) is too large for input file (0x%X) %s\n", - table->length, file_size, pathname); + acpi_log_error + ("Table length (0x%X) is too large for input file (0x%X) %s\n", + table->length, file_size, pathname); goto exit; } if (gbl_verbose_mode) { - fprintf(stderr, - "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", - pathname, table->signature, file_size, file_size); + acpi_log_error + ("Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", + pathname, table->signature, file_size, file_size); } table_status = ap_dump_table_buffer(table, 0, 0); exit: - free(table); + ACPI_FREE(table); return (table_status); } - -/****************************************************************************** - * - * FUNCTION: acpi_os* print functions - * - * DESCRIPTION: Used for linkage with ACPICA modules - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vfprintf(stdout, fmt, args); - va_end(args); -} - -void acpi_os_vprintf(const char *fmt, va_list args) -{ - vfprintf(stdout, fmt, args); -} diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c index 4488accc010b..d470046a6d81 100644 --- a/tools/power/acpi/tools/acpidump/apfiles.c +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -44,6 +44,27 @@ #include "acpidump.h" #include "acapps.h" +/* Local prototypes */ + +static int ap_is_existing_file(char *pathname); + +static int ap_is_existing_file(char *pathname) +{ +#ifndef _GNU_EFI + struct stat stat_info; + + if (!stat(pathname, &stat_info)) { + acpi_log_error("Target path already exists, overwrite? [y|n] "); + + if (getchar() != 'y') { + return (-1); + } + } +#endif + + return 0; +} + /****************************************************************************** * * FUNCTION: ap_open_output_file @@ -59,25 +80,19 @@ int ap_open_output_file(char *pathname) { - struct stat stat_info; - FILE *file; + ACPI_FILE file; /* If file exists, prompt for overwrite */ - if (!stat(pathname, &stat_info)) { - fprintf(stderr, - "Target path already exists, overwrite? [y|n] "); - - if (getchar() != 'y') { - return (-1); - } + if (ap_is_existing_file(pathname) != 0) { + return (-1); } /* Point stdout to the file */ - file = freopen(pathname, "w", stdout); + file = acpi_os_open_file(pathname, ACPI_FILE_WRITING); if (!file) { - perror("Could not open output file"); + acpi_log_error("Could not open output file: %s\n", pathname); return (-1); } @@ -106,7 +121,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) { char filename[ACPI_NAME_SIZE + 16]; char instance_str[16]; - FILE *file; + ACPI_FILE file; size_t actual; u32 table_length; @@ -130,35 +145,37 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) /* Handle multiple SSDts - create different filenames for each */ if (instance > 0) { - sprintf(instance_str, "%u", instance); - strcat(filename, instance_str); + acpi_ut_snprintf(instance_str, sizeof(instance_str), "%u", + instance); + ACPI_STRCAT(filename, instance_str); } - strcat(filename, ACPI_TABLE_FILE_SUFFIX); + ACPI_STRCAT(filename, ACPI_TABLE_FILE_SUFFIX); if (gbl_verbose_mode) { - fprintf(stderr, - "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", - table->signature, filename, table->length, - table->length); + acpi_log_error + ("Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", + table->signature, filename, table->length, table->length); } /* Open the file and dump the entire table in binary mode */ - file = fopen(filename, "wb"); + file = acpi_os_open_file(filename, + ACPI_FILE_WRITING | ACPI_FILE_BINARY); if (!file) { - perror("Could not open output file"); + acpi_log_error("Could not open output file: %s\n", filename); return (-1); } - actual = fwrite(table, 1, table_length, file); + actual = acpi_os_write_file(file, table, 1, table_length); if (actual != table_length) { - perror("Error writing binary output file"); - fclose(file); + acpi_log_error("Error writing binary output file: %s\n", + filename); + acpi_os_close_file(file); return (-1); } - fclose(file); + acpi_os_close_file(file); return (0); } @@ -179,15 +196,16 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, u32 *out_file_size) { struct acpi_table_header *buffer = NULL; - FILE *file; + ACPI_FILE file; u32 file_size; size_t actual; /* Must use binary mode */ - file = fopen(pathname, "rb"); + file = + acpi_os_open_file(pathname, ACPI_FILE_READING | ACPI_FILE_BINARY); if (!file) { - perror("Could not open input file"); + acpi_log_error("Could not open input file: %s\n", pathname); return (NULL); } @@ -195,27 +213,25 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, file_size = cm_get_file_size(file); if (file_size == ACPI_UINT32_MAX) { - fprintf(stderr, - "Could not get input file size: %s\n", pathname); + acpi_log_error("Could not get input file size: %s\n", pathname); goto cleanup; } /* Allocate a buffer for the entire file */ - buffer = calloc(1, file_size); + buffer = ACPI_ALLOCATE_ZEROED(file_size); if (!buffer) { - fprintf(stderr, - "Could not allocate file buffer of size: %u\n", - file_size); + acpi_log_error("Could not allocate file buffer of size: %u\n", + file_size); goto cleanup; } /* Read the entire file */ - actual = fread(buffer, 1, file_size, file); + actual = acpi_os_read_file(file, buffer, 1, file_size); if (actual != file_size) { - fprintf(stderr, "Could not read input file: %s\n", pathname); - free(buffer); + acpi_log_error("Could not read input file: %s\n", pathname); + ACPI_FREE(buffer); buffer = NULL; goto cleanup; } @@ -223,6 +239,6 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, *out_file_size = file_size; cleanup: - fclose(file); + acpi_os_close_file(file); return (buffer); } diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index 51e8d638db18..853b4da22c3e 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -72,7 +72,7 @@ static void ap_display_usage(void); static int ap_do_options(int argc, char **argv); -static void ap_insert_action(char *argument, u32 to_be_done); +static int ap_insert_action(char *argument, u32 to_be_done); /* Table for deferred actions from command line options */ @@ -104,7 +104,7 @@ static void ap_display_usage(void) ACPI_OPTION("-v", "Display version information"); ACPI_OPTION("-z", "Verbose mode"); - printf("\nTable Options:\n"); + ACPI_USAGE_TEXT("\nTable Options:\n"); ACPI_OPTION("-a <Address>", "Get table via a physical address"); ACPI_OPTION("-f <BinaryFile>", "Get table via a binary file"); @@ -112,9 +112,9 @@ static void ap_display_usage(void) ACPI_OPTION("-x", "Do not use but dump XSDT"); ACPI_OPTION("-x -x", "Do not use or dump XSDT"); - printf("\n" - "Invocation without parameters dumps all available tables\n" - "Multiple mixed instances of -a, -f, and -n are supported\n\n"); + ACPI_USAGE_TEXT("\n" + "Invocation without parameters dumps all available tables\n" + "Multiple mixed instances of -a, -f, and -n are supported\n\n"); } /****************************************************************************** @@ -124,13 +124,13 @@ static void ap_display_usage(void) * PARAMETERS: argument - Pointer to the argument for this action * to_be_done - What to do to process this action * - * RETURN: None. Exits program if action table becomes full. + * RETURN: Status * * DESCRIPTION: Add an action item to the action table * ******************************************************************************/ -static void ap_insert_action(char *argument, u32 to_be_done) +static int ap_insert_action(char *argument, u32 to_be_done) { /* Insert action and check for table overflow */ @@ -140,10 +140,12 @@ static void ap_insert_action(char *argument, u32 to_be_done) current_action++; if (current_action > AP_MAX_ACTIONS) { - fprintf(stderr, "Too many table options (max %u)\n", - AP_MAX_ACTIONS); - exit(-1); + acpi_log_error("Too many table options (max %u)\n", + AP_MAX_ACTIONS); + return (-1); } + + return (0); } /****************************************************************************** @@ -166,7 +168,8 @@ static int ap_do_options(int argc, char **argv) /* Command line options */ - while ((j = acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != EOF) + while ((j = + acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != ACPI_OPT_END) switch (j) { /* * Global options @@ -185,12 +188,12 @@ static int ap_do_options(int argc, char **argv) case '?': ap_display_usage(); - exit(0); + return (1); case 'o': /* Redirect output to a single file */ if (ap_open_output_file(acpi_gbl_optarg)) { - exit(-1); + return (-1); } continue; @@ -200,10 +203,10 @@ static int ap_do_options(int argc, char **argv) acpi_ut_strtoul64(acpi_gbl_optarg, 0, &gbl_rsdp_base); if (ACPI_FAILURE(status)) { - fprintf(stderr, - "%s: Could not convert to a physical address\n", - acpi_gbl_optarg); - exit(-1); + acpi_log_error + ("%s: Could not convert to a physical address\n", + acpi_gbl_optarg); + return (-1); } continue; @@ -223,13 +226,13 @@ static int ap_do_options(int argc, char **argv) case 'v': /* Revision/version */ - printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); - exit(0); + acpi_os_printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + return (1); case 'z': /* Verbose mode */ gbl_verbose_mode = TRUE; - fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + acpi_log_error(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); continue; /* @@ -237,32 +240,40 @@ static int ap_do_options(int argc, char **argv) */ case 'a': /* Get table by physical address */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_ADDRESS); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_ADDRESS)) { + return (-1); + } break; case 'f': /* Get table from a file */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_FILE); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_FILE)) { + return (-1); + } break; case 'n': /* Get table by input name (signature) */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_NAME); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_NAME)) { + return (-1); + } break; default: ap_display_usage(); - exit(-1); + return (-1); } /* If there are no actions, this means "get/dump all tables" */ if (current_action == 0) { - ap_insert_action(NULL, AP_DUMP_ALL_TABLES); + if (ap_insert_action(NULL, AP_DUMP_ALL_TABLES)) { + return (-1); + } } return (0); @@ -280,7 +291,11 @@ static int ap_do_options(int argc, char **argv) * ******************************************************************************/ +#ifndef _GNU_EFI int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) +#else +int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) +#endif { int status = 0; struct ap_dump_action *action; @@ -288,11 +303,17 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) u32 i; ACPI_DEBUG_INITIALIZE(); /* For debug version only */ + acpi_os_initialize(); + gbl_output_file = ACPI_FILE_OUT; /* Process command line options */ - if (ap_do_options(argc, argv)) { - return (-1); + status = ap_do_options(argc, argv); + if (status > 0) { + return (0); + } + if (status < 0) { + return (status); } /* Get/dump ACPI table(s) as requested */ @@ -322,9 +343,8 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) default: - fprintf(stderr, - "Internal error, invalid action: 0x%X\n", - action->to_be_done); + acpi_log_error("Internal error, invalid action: 0x%X\n", + action->to_be_done); return (-1); } @@ -333,18 +353,18 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) } } - if (gbl_output_file) { + if (gbl_output_filename) { if (gbl_verbose_mode) { /* Summary for the output file */ file_size = cm_get_file_size(gbl_output_file); - fprintf(stderr, - "Output file %s contains 0x%X (%u) bytes\n\n", - gbl_output_filename, file_size, file_size); + acpi_log_error + ("Output file %s contains 0x%X (%u) bytes\n\n", + gbl_output_filename, file_size, file_size); } - fclose(gbl_output_file); + acpi_os_close_file(gbl_output_file); } return (status); diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c index 543bba14ae2c..f503fb53824e 100644 --- a/tools/power/cpupower/bench/parse.c +++ b/tools/power/cpupower/bench/parse.c @@ -158,14 +158,15 @@ struct config *prepare_default_config() int prepare_config(const char *path, struct config *config) { size_t len = 0; - char *opt, *val, *line = NULL; - FILE *configfile = fopen(path, "r"); + char opt[16], val[32], *line = NULL; + FILE *configfile; if (config == NULL) { fprintf(stderr, "error: config is NULL\n"); return 1; } + configfile = fopen(path, "r"); if (configfile == NULL) { perror("fopen"); fprintf(stderr, "error: unable to read configfile\n"); @@ -174,52 +175,54 @@ int prepare_config(const char *path, struct config *config) } while (getline(&line, &len, configfile) != -1) { - if (line[0] == '#' || line[0] == ' ') + if (line[0] == '#' || line[0] == ' ' || line[0] == '\n') continue; - sscanf(line, "%as = %as", &opt, &val); + if (sscanf(line, "%14s = %30s", opt, val) < 2) + continue; dprintf("parsing: %s -> %s\n", opt, val); - if (strncmp("sleep", opt, strlen(opt)) == 0) + if (strcmp("sleep", opt) == 0) sscanf(val, "%li", &config->sleep); - else if (strncmp("load", opt, strlen(opt)) == 0) + else if (strcmp("load", opt) == 0) sscanf(val, "%li", &config->load); - else if (strncmp("load_step", opt, strlen(opt)) == 0) + else if (strcmp("load_step", opt) == 0) sscanf(val, "%li", &config->load_step); - else if (strncmp("sleep_step", opt, strlen(opt)) == 0) + else if (strcmp("sleep_step", opt) == 0) sscanf(val, "%li", &config->sleep_step); - else if (strncmp("cycles", opt, strlen(opt)) == 0) + else if (strcmp("cycles", opt) == 0) sscanf(val, "%u", &config->cycles); - else if (strncmp("rounds", opt, strlen(opt)) == 0) + else if (strcmp("rounds", opt) == 0) sscanf(val, "%u", &config->rounds); - else if (strncmp("verbose", opt, strlen(opt)) == 0) + else if (strcmp("verbose", opt) == 0) sscanf(val, "%u", &config->verbose); - else if (strncmp("output", opt, strlen(opt)) == 0) + else if (strcmp("output", opt) == 0) config->output = prepare_output(val); - else if (strncmp("cpu", opt, strlen(opt)) == 0) + else if (strcmp("cpu", opt) == 0) sscanf(val, "%u", &config->cpu); - else if (strncmp("governor", opt, 14) == 0) - strncpy(config->governor, val, 14); + else if (strcmp("governor", opt) == 0) { + strncpy(config->governor, val, + sizeof(config->governor)); + config->governor[sizeof(config->governor) - 1] = '\0'; + } - else if (strncmp("priority", opt, strlen(opt)) == 0) { + else if (strcmp("priority", opt) == 0) { if (string_to_prio(val) != SCHED_ERR) config->prio = string_to_prio(val); } } free(line); - free(opt); - free(val); return 0; } diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c index a416de80c55e..f656e585ed45 100644 --- a/tools/power/cpupower/utils/cpufreq-set.c +++ b/tools/power/cpupower/utils/cpufreq-set.c @@ -320,12 +320,11 @@ int cmd_freq_set(int argc, char **argv) printf(_("Setting cpu: %d\n"), cpu); ret = do_one_cpu(cpu, &new_pol, freq, policychange); - if (ret) - break; + if (ret) { + print_error(); + return ret; + } } - if (ret) - print_error(); - - return ret; + return 0; } diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 851c7a16ca49..09afe5d87f2b 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c @@ -81,7 +81,7 @@ int sysfs_is_cpu_online(unsigned int cpu) close(fd); value = strtoull(linebuf, &endp, 0); - if (value > 1 || value < 0) + if (value > 1) return -EINVAL; return value; diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c index 5650ab5a2c20..90a8c4f071e7 100644 --- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c @@ -237,7 +237,7 @@ static int init_maxfreq_mode(void) unsigned long long hwcr; unsigned long min; - if (!cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC) + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC)) goto use_sysfs; if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) { |