summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/acpi.h23
-rw-r--r--arch/x86/kernel/acpi/apei.c3
-rw-r--r--drivers/acpi/acpi_apd.c7
-rw-r--r--drivers/acpi/acpi_lpss.c8
-rw-r--r--drivers/acpi/acpi_video.c11
-rw-r--r--drivers/acpi/apei/ghes.c7
-rw-r--r--drivers/acpi/apei/hest.c13
-rw-r--r--drivers/acpi/battery.c72
-rw-r--r--drivers/acpi/cppc_acpi.c4
-rw-r--r--drivers/acpi/video_detect.c20
-rw-r--r--include/acpi/video.h11
12 files changed, 130 insertions, 50 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef880d234..657be7f5014e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -52,6 +52,7 @@ config ARM64
select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
+ select HAVE_ACPI_APEI if (ACPI && EFI)
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index e517088d635f..d0de0e032bc2 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -17,6 +17,7 @@
#include <asm/cputype.h>
#include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
/* Macros for consistency checks of the GICC subtable of MADT */
#define ACPI_MADT_GICC_LENGTH \
@@ -114,8 +115,28 @@ static inline const char *acpi_get_enable_method(int cpu)
}
#ifdef CONFIG_ACPI_APEI
+/*
+ * acpi_disable_cmcff is used in drivers/acpi/apei/hest.c for disabling
+ * IA-32 Architecture Corrected Machine Check (CMC) Firmware-First mode
+ * with a kernel command line parameter "acpi=nocmcoff". But we don't
+ * have this IA-32 specific feature on ARM64, this definition is only
+ * for compatibility.
+ */
+#define acpi_disable_cmcff 1
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
-#endif
+
+/*
+ * Despite its name, this function must still broadcast the TLB
+ * invalidation in order to ensure other CPUs don't end up with junk
+ * entries as a result of speculation. Unusually, its also called in
+ * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for
+ * TLB broadcasting, then we're in trouble here.
+ */
+static inline void arch_apei_flush_tlb_one(unsigned long addr)
+{
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+}
+#endif /* CONFIG_ACPI_APEI */
#ifdef CONFIG_ACPI_NUMA
int arm64_acpi_numa_init(void);
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
index c280df6b2aa2..ea3046e0b0cf 100644
--- a/arch/x86/kernel/acpi/apei.c
+++ b/arch/x86/kernel/acpi/apei.c
@@ -24,9 +24,6 @@ int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data)
struct acpi_hest_ia_corrected *cmc;
struct acpi_hest_ia_error_bank *mc_bank;
- if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
- return 0;
-
cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
if (!cmc->enabled)
return 0;
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 7dd70927991e..26696b693e63 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -77,6 +77,11 @@ static const struct apd_device_desc cz_i2c_desc = {
.fixed_clk_rate = 133000000,
};
+static const struct apd_device_desc wt_i2c_desc = {
+ .setup = acpi_apd_setup,
+ .fixed_clk_rate = 150000000,
+};
+
static struct property_entry uart_properties[] = {
PROPERTY_ENTRY_U32("reg-io-width", 4),
PROPERTY_ENTRY_U32("reg-shift", 2),
@@ -156,7 +161,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
/* Generic apd devices */
#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
{ "AMD0010", APD_ADDR(cz_i2c_desc) },
- { "AMDI0010", APD_ADDR(cz_i2c_desc) },
+ { "AMDI0010", APD_ADDR(wt_i2c_desc) },
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 373657f7e35a..8ea836c046f8 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -718,13 +718,14 @@ static int acpi_lpss_resume_early(struct device *dev)
#define LPSS_GPIODEF0_DMA1_D3 BIT(2)
#define LPSS_GPIODEF0_DMA2_D3 BIT(3)
#define LPSS_GPIODEF0_DMA_D3_MASK GENMASK(3, 2)
+#define LPSS_GPIODEF0_DMA_LLP BIT(13)
static DEFINE_MUTEX(lpss_iosf_mutex);
static void lpss_iosf_enter_d3_state(void)
{
u32 value1 = 0;
- u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+ u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP;
u32 value2 = LPSS_PMCSR_D3hot;
u32 mask2 = LPSS_PMCSR_Dx_MASK;
/*
@@ -768,8 +769,9 @@ exit:
static void lpss_iosf_exit_d3_state(void)
{
- u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3;
- u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+ u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3 |
+ LPSS_GPIODEF0_DMA_LLP;
+ u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP;
u32 value2 = LPSS_PMCSR_D0;
u32 mask2 = LPSS_PMCSR_Dx_MASK;
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index c5557d070954..201292e67ee8 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -43,17 +43,6 @@
#define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
-#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
-#define ACPI_VIDEO_NOTIFY_PROBE 0x81
-#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
-#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
-#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
-
-#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85
-#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
-#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
-#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
-#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
#define MAX_NAME_LEN 20
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 0d099a24f776..e53bef6cf53c 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -852,6 +852,8 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
if (ghes_read_estatus(ghes, 1)) {
ghes_clear_estatus(ghes);
continue;
+ } else {
+ ret = NMI_HANDLED;
}
sev = ghes_severity(ghes->estatus->error_severity);
@@ -863,12 +865,11 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
__process_error(ghes);
ghes_clear_estatus(ghes);
-
- ret = NMI_HANDLED;
}
#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
- irq_work_queue(&ghes_proc_irq_work);
+ if (ret == NMI_HANDLED)
+ irq_work_queue(&ghes_proc_irq_work);
#endif
atomic_dec(&ghes_in_nmi);
return ret;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 20b3fcf4007c..8f2a98e23bba 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -123,7 +123,13 @@ EXPORT_SYMBOL_GPL(apei_hest_parse);
*/
static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
{
- return arch_apei_enable_cmcff(hest_hdr, data);
+ if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
+ return 0;
+
+ if (!acpi_disable_cmcff)
+ return !arch_apei_enable_cmcff(hest_hdr, data);
+
+ return 0;
}
struct ghes_arr {
@@ -232,8 +238,9 @@ void __init acpi_hest_init(void)
goto err;
}
- if (!acpi_disable_cmcff)
- apei_hest_parse(hest_parse_cmc, NULL);
+ rc = apei_hest_parse(hest_parse_cmc, NULL);
+ if (rc)
+ goto err;
if (!ghes_disable) {
rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 93ecae55fe6a..05fe9ebfb9b5 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -430,39 +430,24 @@ static int acpi_battery_get_status(struct acpi_battery *battery)
return 0;
}
-static int acpi_battery_get_info(struct acpi_battery *battery)
+
+static int extract_battery_info(const int use_bix,
+ struct acpi_battery *battery,
+ const struct acpi_buffer *buffer)
{
int result = -EFAULT;
- acpi_status status = 0;
- char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
- "_BIX" : "_BIF";
-
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- if (!acpi_battery_present(battery))
- return 0;
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(battery->device->handle, name,
- NULL, &buffer);
- mutex_unlock(&battery->lock);
-
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
- return -ENODEV;
- }
-
- if (battery_bix_broken_package)
- result = extract_package(battery, buffer.pointer,
+ if (use_bix && battery_bix_broken_package)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets + 1,
ARRAY_SIZE(extended_info_offsets) - 1);
- else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
- result = extract_package(battery, buffer.pointer,
+ else if (use_bix)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
else
- result = extract_package(battery, buffer.pointer,
+ result = extract_package(battery, buffer->pointer,
info_offsets, ARRAY_SIZE(info_offsets));
- kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
@@ -483,6 +468,45 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return result;
}
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+ const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+ int use_bix;
+ int result = -ENODEV;
+
+ if (!acpi_battery_present(battery))
+ return 0;
+
+
+ for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_status status = AE_ERROR;
+
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle,
+ use_bix ? "_BIX":"_BIF",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
+ use_bix ? "_BIX":"_BIF"));
+ } else {
+ result = extract_battery_info(use_bix,
+ battery,
+ &buffer);
+
+ kfree(buffer.pointer);
+ break;
+ }
+ }
+
+ if (!result && !use_bix && xinfo)
+ pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
+
+ return result;
+}
+
static int acpi_battery_get_state(struct acpi_battery *battery)
{
int result = 0;
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index d0d0504b7c89..e0ea8f56d2bf 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -784,8 +784,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
/* Add per logical CPU nodes for reading its feedback counters. */
cpu_dev = get_cpu_device(pr->id);
- if (!cpu_dev)
+ if (!cpu_dev) {
+ ret = -EINVAL;
goto out_free;
+ }
ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj,
"acpi_cppc");
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index a6b36fc53aec..02ded25c82e4 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -296,6 +296,26 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
},
},
+ {
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
+ .callback = video_detect_force_native,
+ .ident = "Dell XPS 17 L702X",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
+ },
+ },
+ {
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */
+ /* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */
+ .callback = video_detect_force_native,
+ .ident = "HP Pavilion dv6",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"),
+ },
+ },
+
{ },
};
diff --git a/include/acpi/video.h b/include/acpi/video.h
index 4536bd345ab4..bfe484da55d2 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -30,6 +30,17 @@ struct acpi_device;
#define ACPI_VIDEO_DISPLAY_LEGACY_PANEL 0x0110
#define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200
+#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
+#define ACPI_VIDEO_NOTIFY_PROBE 0x81
+#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
+#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
+#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
+#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85
+#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
+#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
+#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
+#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
+
enum acpi_backlight_type {
acpi_backlight_undef = -1,
acpi_backlight_none = 0,