diff options
-rw-r--r-- | drivers/acpi/acpi_video.c | 27 | ||||
-rw-r--r-- | drivers/acpi/acpi_watchdog.c | 59 | ||||
-rw-r--r-- | drivers/acpi/button.c | 24 |
3 files changed, 97 insertions, 13 deletions
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 76fb96966f7b..2f2e737be0f8 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c | |||
@@ -2123,6 +2123,25 @@ static int __init intel_opregion_present(void) | |||
2123 | return opregion; | 2123 | return opregion; |
2124 | } | 2124 | } |
2125 | 2125 | ||
2126 | static bool dmi_is_desktop(void) | ||
2127 | { | ||
2128 | const char *chassis_type; | ||
2129 | |||
2130 | chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); | ||
2131 | if (!chassis_type) | ||
2132 | return false; | ||
2133 | |||
2134 | if (!strcmp(chassis_type, "3") || /* 3: Desktop */ | ||
2135 | !strcmp(chassis_type, "4") || /* 4: Low Profile Desktop */ | ||
2136 | !strcmp(chassis_type, "5") || /* 5: Pizza Box */ | ||
2137 | !strcmp(chassis_type, "6") || /* 6: Mini Tower */ | ||
2138 | !strcmp(chassis_type, "7") || /* 7: Tower */ | ||
2139 | !strcmp(chassis_type, "11")) /* 11: Main Server Chassis */ | ||
2140 | return true; | ||
2141 | |||
2142 | return false; | ||
2143 | } | ||
2144 | |||
2126 | int acpi_video_register(void) | 2145 | int acpi_video_register(void) |
2127 | { | 2146 | { |
2128 | int ret = 0; | 2147 | int ret = 0; |
@@ -2143,8 +2162,12 @@ int acpi_video_register(void) | |||
2143 | * win8 ready (where we also prefer the native backlight driver, so | 2162 | * win8 ready (where we also prefer the native backlight driver, so |
2144 | * normally the acpi_video code should not register there anyways). | 2163 | * normally the acpi_video code should not register there anyways). |
2145 | */ | 2164 | */ |
2146 | if (only_lcd == -1) | 2165 | if (only_lcd == -1) { |
2147 | only_lcd = acpi_osi_is_win8(); | 2166 | if (dmi_is_desktop() && acpi_osi_is_win8()) |
2167 | only_lcd = true; | ||
2168 | else | ||
2169 | only_lcd = false; | ||
2170 | } | ||
2148 | 2171 | ||
2149 | dmi_check_system(video_dmi_table); | 2172 | dmi_check_system(video_dmi_table); |
2150 | 2173 | ||
diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index ebb626ffb5fa..4bde16fb97d8 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c | |||
@@ -12,23 +12,64 @@ | |||
12 | #define pr_fmt(fmt) "ACPI: watchdog: " fmt | 12 | #define pr_fmt(fmt) "ACPI: watchdog: " fmt |
13 | 13 | ||
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <linux/dmi.h> | ||
15 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | 18 | ||
18 | #include "internal.h" | 19 | #include "internal.h" |
19 | 20 | ||
21 | static const struct dmi_system_id acpi_watchdog_skip[] = { | ||
22 | { | ||
23 | /* | ||
24 | * On Lenovo Z50-70 there are two issues with the WDAT | ||
25 | * table. First some of the instructions use RTC SRAM | ||
26 | * to store persistent information. This does not work well | ||
27 | * with Linux RTC driver. Second, more important thing is | ||
28 | * that the instructions do not actually reset the system. | ||
29 | * | ||
30 | * On this particular system iTCO_wdt seems to work just | ||
31 | * fine so we prefer that over WDAT for now. | ||
32 | * | ||
33 | * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033. | ||
34 | */ | ||
35 | .ident = "Lenovo Z50-70", | ||
36 | .matches = { | ||
37 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
38 | DMI_MATCH(DMI_PRODUCT_NAME, "20354"), | ||
39 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"), | ||
40 | }, | ||
41 | }, | ||
42 | {} | ||
43 | }; | ||
44 | |||
45 | static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) | ||
46 | { | ||
47 | const struct acpi_table_wdat *wdat = NULL; | ||
48 | acpi_status status; | ||
49 | |||
50 | if (acpi_disabled) | ||
51 | return NULL; | ||
52 | |||
53 | if (dmi_check_system(acpi_watchdog_skip)) | ||
54 | return NULL; | ||
55 | |||
56 | status = acpi_get_table(ACPI_SIG_WDAT, 0, | ||
57 | (struct acpi_table_header **)&wdat); | ||
58 | if (ACPI_FAILURE(status)) { | ||
59 | /* It is fine if there is no WDAT */ | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | return wdat; | ||
64 | } | ||
65 | |||
20 | /** | 66 | /** |
21 | * Returns true if this system should prefer ACPI based watchdog instead of | 67 | * Returns true if this system should prefer ACPI based watchdog instead of |
22 | * the native one (which are typically the same hardware). | 68 | * the native one (which are typically the same hardware). |
23 | */ | 69 | */ |
24 | bool acpi_has_watchdog(void) | 70 | bool acpi_has_watchdog(void) |
25 | { | 71 | { |
26 | struct acpi_table_header hdr; | 72 | return !!acpi_watchdog_get_wdat(); |
27 | |||
28 | if (acpi_disabled) | ||
29 | return false; | ||
30 | |||
31 | return ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_WDAT, 0, &hdr)); | ||
32 | } | 73 | } |
33 | EXPORT_SYMBOL_GPL(acpi_has_watchdog); | 74 | EXPORT_SYMBOL_GPL(acpi_has_watchdog); |
34 | 75 | ||
@@ -41,12 +82,10 @@ void __init acpi_watchdog_init(void) | |||
41 | struct platform_device *pdev; | 82 | struct platform_device *pdev; |
42 | struct resource *resources; | 83 | struct resource *resources; |
43 | size_t nresources = 0; | 84 | size_t nresources = 0; |
44 | acpi_status status; | ||
45 | int i; | 85 | int i; |
46 | 86 | ||
47 | status = acpi_get_table(ACPI_SIG_WDAT, 0, | 87 | wdat = acpi_watchdog_get_wdat(); |
48 | (struct acpi_table_header **)&wdat); | 88 | if (!wdat) { |
49 | if (ACPI_FAILURE(status)) { | ||
50 | /* It is fine if there is no WDAT */ | 89 | /* It is fine if there is no WDAT */ |
51 | return; | 90 | return; |
52 | } | 91 | } |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index e1eee7a60fad..f1cc4f9d31cd 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -635,4 +635,26 @@ module_param_call(lid_init_state, | |||
635 | NULL, 0644); | 635 | NULL, 0644); |
636 | MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state"); | 636 | MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state"); |
637 | 637 | ||
638 | module_acpi_driver(acpi_button_driver); | 638 | static int acpi_button_register_driver(struct acpi_driver *driver) |
639 | { | ||
640 | /* | ||
641 | * Modules such as nouveau.ko and i915.ko have a link time dependency | ||
642 | * on acpi_lid_open(), and would therefore not be loadable on ACPI | ||
643 | * capable kernels booted in non-ACPI mode if the return value of | ||
644 | * acpi_bus_register_driver() is returned from here with ACPI disabled | ||
645 | * when this driver is built as a module. | ||
646 | */ | ||
647 | if (acpi_disabled) | ||
648 | return 0; | ||
649 | |||
650 | return acpi_bus_register_driver(driver); | ||
651 | } | ||
652 | |||
653 | static void acpi_button_unregister_driver(struct acpi_driver *driver) | ||
654 | { | ||
655 | if (!acpi_disabled) | ||
656 | acpi_bus_unregister_driver(driver); | ||
657 | } | ||
658 | |||
659 | module_driver(acpi_button_driver, acpi_button_register_driver, | ||
660 | acpi_button_unregister_driver); | ||