Merge branches 'acpi-watchdog', 'acpi-button' and 'acpi-video'

* acpi-watchdog:
  ACPI / watchdog: Prefer iTCO_wdt on Lenovo Z50-70

* acpi-button:
  ACPI / button: make module loadable when booted in non-ACPI mode

* acpi-video:
  ACPI / video: Only default only_lcd to true on Win8-ready _desktops_
This commit is contained in:
Rafael J. Wysocki 2018-04-26 15:11:39 +02:00
commit bd6dff55de
3 changed files with 97 additions and 13 deletions

View File

@ -2123,6 +2123,25 @@ static int __init intel_opregion_present(void)
return opregion;
}
static bool dmi_is_desktop(void)
{
const char *chassis_type;
chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
if (!chassis_type)
return false;
if (!strcmp(chassis_type, "3") || /* 3: Desktop */
!strcmp(chassis_type, "4") || /* 4: Low Profile Desktop */
!strcmp(chassis_type, "5") || /* 5: Pizza Box */
!strcmp(chassis_type, "6") || /* 6: Mini Tower */
!strcmp(chassis_type, "7") || /* 7: Tower */
!strcmp(chassis_type, "11")) /* 11: Main Server Chassis */
return true;
return false;
}
int acpi_video_register(void)
{
int ret = 0;
@ -2143,8 +2162,12 @@ int acpi_video_register(void)
* win8 ready (where we also prefer the native backlight driver, so
* normally the acpi_video code should not register there anyways).
*/
if (only_lcd == -1)
only_lcd = acpi_osi_is_win8();
if (only_lcd == -1) {
if (dmi_is_desktop() && acpi_osi_is_win8())
only_lcd = true;
else
only_lcd = false;
}
dmi_check_system(video_dmi_table);

View File

@ -12,23 +12,64 @@
#define pr_fmt(fmt) "ACPI: watchdog: " fmt
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include "internal.h"
static const struct dmi_system_id acpi_watchdog_skip[] = {
{
/*
* On Lenovo Z50-70 there are two issues with the WDAT
* table. First some of the instructions use RTC SRAM
* to store persistent information. This does not work well
* with Linux RTC driver. Second, more important thing is
* that the instructions do not actually reset the system.
*
* On this particular system iTCO_wdt seems to work just
* fine so we prefer that over WDAT for now.
*
* See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
*/
.ident = "Lenovo Z50-70",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20354"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"),
},
},
{}
};
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
{
const struct acpi_table_wdat *wdat = NULL;
acpi_status status;
if (acpi_disabled)
return NULL;
if (dmi_check_system(acpi_watchdog_skip))
return NULL;
status = acpi_get_table(ACPI_SIG_WDAT, 0,
(struct acpi_table_header **)&wdat);
if (ACPI_FAILURE(status)) {
/* It is fine if there is no WDAT */
return NULL;
}
return wdat;
}
/**
* Returns true if this system should prefer ACPI based watchdog instead of
* the native one (which are typically the same hardware).
*/
bool acpi_has_watchdog(void)
{
struct acpi_table_header hdr;
if (acpi_disabled)
return false;
return ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_WDAT, 0, &hdr));
return !!acpi_watchdog_get_wdat();
}
EXPORT_SYMBOL_GPL(acpi_has_watchdog);
@ -41,12 +82,10 @@ void __init acpi_watchdog_init(void)
struct platform_device *pdev;
struct resource *resources;
size_t nresources = 0;
acpi_status status;
int i;
status = acpi_get_table(ACPI_SIG_WDAT, 0,
(struct acpi_table_header **)&wdat);
if (ACPI_FAILURE(status)) {
wdat = acpi_watchdog_get_wdat();
if (!wdat) {
/* It is fine if there is no WDAT */
return;
}

View File

@ -635,4 +635,26 @@ module_param_call(lid_init_state,
NULL, 0644);
MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
module_acpi_driver(acpi_button_driver);
static int acpi_button_register_driver(struct acpi_driver *driver)
{
/*
* Modules such as nouveau.ko and i915.ko have a link time dependency
* on acpi_lid_open(), and would therefore not be loadable on ACPI
* capable kernels booted in non-ACPI mode if the return value of
* acpi_bus_register_driver() is returned from here with ACPI disabled
* when this driver is built as a module.
*/
if (acpi_disabled)
return 0;
return acpi_bus_register_driver(driver);
}
static void acpi_button_unregister_driver(struct acpi_driver *driver)
{
if (!acpi_disabled)
acpi_bus_unregister_driver(driver);
}
module_driver(acpi_button_driver, acpi_button_register_driver,
acpi_button_unregister_driver);