Commit bb695055 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'acpi-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI updates from Rafael Wysocki:
 "These rework the handling of notifications in ACPI button drivers (to
  enable future simplifications and cleanups), clean up the ACPI thermal
  driver, update the ACPI backlight driver, add quirks working around
  AML bugs on some systems, fix some assorted issues and clean up code.

  Specifics:

   - Reduce ACPI device enumeration overhead related to devices with
     dependencies (Rafael Wysocki)

   - Fix the handling of Microsoft LPS0 _DSM for suspend-to-idle (Mario
     Limonciello)

   - Fix section mismatch warning in the ACPI suspend-to-idle code (Arnd
     Bergmann)

   - Drop several ACPI resource management quirks related to IRQ
     ovverides on AMD "Zen" systems (Mario Limonciello)

   - Modify the ACPI EC driver to make it only clear the EC GPE status
     when handling the GPE (Jeremy Compostella)

   - Add quirks to work around ACPI tables defects on Lenovo Yoga Book
     yb1-x90f/l and Nextbook Ares 8A (Hans de Goede)

   - Add ACPi backlight quirks for Dell Studio 1569, Lenovo ThinkPad
     X131e (3371 AMD version) and Apple iMac11,3 and stop trying to use
     vendor backlight control on relatively recent systems (Hans de
     Goede)

   - Add pwm_lookup_table entry for second PWM on CHT/BSW devices in the
     ACPI LPSS (Intel SoC) driver (Hans de Goede)

   - Add nfit_intel_shutdown_status() declaration to a local header to
     avoid a "missing prototypes" build warning (Arnd Bergmann)

   - Clean up the ACPI thermal driver and drop some dead or otherwise
     unneded code from it (Rafael Wysocki)

   - Rework the handling of notifications in the ACPI button drivers so
     as to allow the common notification handling code for devices to be
     simplified (Rafael Wysocki)

   - Make ghes_get_devices() return NULL to indicate that there are no
     GHES devices so as to allow vendor-specific EDAC drivers to probe
     then (Li Yang)

   - Mark bert_disable() as __initdata and drop an unused function from
     the APEI GHES code (Miaohe Lin)

   - Make the ACPI PAD (Processor Aggregator Device) driver realize that
     Zhaoxin CPUs support nonstop TSC (Tony W Wang-oc)

   - Drop the certainly unnecessary and likely incorrect inclusion of
     linux/arm-smccc.h from acpi_ffh.c (Sudeep Holla)"

* tag 'acpi-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (30 commits)
  ACPI: video: Add backlight=native DMI quirk for Dell Studio 1569
  ACPI: thermal: Drop struct acpi_thermal_flags
  ACPI: thermal: Drop struct acpi_thermal_state
  ACPI: bus: Simplify installation and removal of notify callback
  ACPI: tiny-power-button: Eliminate the driver notify callback
  ACPI: button: Use different notify handlers for lid and buttons
  ACPI: button: Eliminate the driver notify callback
  ACPI: thermal: Eliminate struct acpi_thermal_state_flags
  ACPI: thermal: Move acpi_thermal_driver definition
  ACPI: thermal: Move symbol definitions to one place
  ACPI: thermal: Drop redundant ACPI_TRIPS_REFRESH_DEVICES symbol
  ACPI: thermal: Use BIT() macro for defining flags
  APEI: GHES: correctly return NULL for ghes_get_devices()
  ACPI: FFH: Drop the inclusion of linux/arm-smccc.h
  ACPI: PAD: mark Zhaoxin CPUs NONSTOP TSC correctly
  ACPI: APEI: mark bert_disable as __initdata
  ACPI: EC: Clear GPE on interrupt handling only
  ACPI: video: Stop trying to use vendor backlight control on laptops from after ~2012
  ACPI: x86: s2idle: Adjust Microsoft LPS0 _DSM handling sequence
  ACPI: resource: Remove "Zen" specific match and quirks
  ...
parents 2605e80d 01fee479
......@@ -9,8 +9,6 @@
#include <linux/idr.h>
#include <linux/io.h>
#include <linux/arm-smccc.h>
static struct acpi_ffh_info ffh_ctx;
int __weak acpi_ffh_address_space_arch_setup(void *handler_ctxt,
......
......@@ -201,11 +201,19 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
}
/* BSW PWM used for backlight control by the i915 driver */
/*
* BSW PWM1 is used for backlight control by the i915 driver
* BSW PWM2 is used for backlight control for fixed (etched into the glass)
* touch controls on some models. These touch-controls have specialized
* drivers which know they need the "pwm_soc_lpss_2" con-id.
*/
static struct pwm_lookup bsw_pwm_lookup[] = {
PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0",
"pwm_soc_backlight", 0, PWM_POLARITY_NORMAL,
"pwm-lpss-platform"),
PWM_LOOKUP_WITH_MODULE("80862289:00", 0, NULL,
"pwm_soc_lpss_2", 0, PWM_POLARITY_NORMAL,
"pwm-lpss-platform"),
};
static void bsw_pwm_setup(struct lpss_private_data *pdata)
......
......@@ -66,6 +66,7 @@ static void power_saving_mwait_init(void)
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
case X86_VENDOR_ZHAOXIN:
case X86_VENDOR_CENTAUR:
/*
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
......
......@@ -34,7 +34,7 @@
#define ACPI_BERT_PRINT_MAX_RECORDS 5
#define ACPI_BERT_PRINT_MAX_LEN 1024
static int bert_disable;
static int bert_disable __initdata;
/*
* Print "all" the error records in the BERT table, but avoid huge spam to
......
......@@ -152,7 +152,6 @@ struct ghes_vendor_record_entry {
};
static struct gen_pool *ghes_estatus_pool;
static unsigned long ghes_estatus_pool_size_request;
static struct ghes_estatus_cache __rcu *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
......@@ -191,7 +190,6 @@ int ghes_estatus_pool_init(unsigned int num_ghes)
len = GHES_ESTATUS_CACHE_AVG_SIZE * GHES_ESTATUS_CACHE_ALLOCED_MAX;
len += (num_ghes * GHES_ESOURCE_PREALLOC_MAX_SIZE);
ghes_estatus_pool_size_request = PAGE_ALIGN(len);
addr = (unsigned long)vmalloc(PAGE_ALIGN(len));
if (!addr)
goto err_pool_alloc;
......@@ -1544,6 +1542,8 @@ struct list_head *ghes_get_devices(void)
pr_warn_once("Force-loading ghes_edac on an unsupported platform. You're on your own!\n");
}
} else if (list_empty(&ghes_devs)) {
return NULL;
}
return &ghes_devs;
......
......@@ -527,65 +527,30 @@ static void acpi_notify_device(acpi_handle handle, u32 event, void *data)
acpi_drv->ops.notify(device, event);
}
static void acpi_notify_device_fixed(void *data)
{
struct acpi_device *device = data;
/* Fixed hardware devices have no handles */
acpi_notify_device(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
}
static u32 acpi_device_fixed_event(void *data)
{
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_notify_device_fixed, data);
return ACPI_INTERRUPT_HANDLED;
}
static int acpi_device_install_notify_handler(struct acpi_device *device,
struct acpi_driver *acpi_drv)
{
acpi_status status;
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
status =
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_device_fixed_event,
device);
} else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
status =
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
acpi_device_fixed_event,
device);
} else {
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
acpi_status status;
status = acpi_install_notify_handler(device->handle, type,
acpi_notify_device,
device);
}
status = acpi_install_notify_handler(device->handle, type,
acpi_notify_device, device);
if (ACPI_FAILURE(status))
return -EINVAL;
return 0;
}
static void acpi_device_remove_notify_handler(struct acpi_device *device,
struct acpi_driver *acpi_drv)
{
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_device_fixed_event);
} else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
acpi_device_fixed_event);
} else {
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
acpi_remove_notify_handler(device->handle, type,
acpi_notify_device);
}
acpi_remove_notify_handler(device->handle, type,
acpi_notify_device);
acpi_os_wait_events_complete();
}
......
......@@ -77,6 +77,15 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
},
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
},
{
/* Nextbook Ares 8A tablet, _LID device always reports lid closed */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
DMI_MATCH(DMI_BIOS_VERSION, "M882"),
},
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
},
{
/*
* Lenovo Yoga 9 14ITL5, initial notification of the LID device
......@@ -126,7 +135,6 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
static int acpi_button_add(struct acpi_device *device);
static void 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);
......@@ -144,7 +152,6 @@ static struct acpi_driver acpi_button_driver = {
.ops = {
.add = acpi_button_add,
.remove = acpi_button_remove,
.notify = acpi_button_notify,
},
.drv.pm = &acpi_button_pm,
};
......@@ -400,45 +407,65 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
button->lid_state_initialized = true;
}
static void acpi_button_notify(struct acpi_device *device, u32 event)
static void acpi_lid_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_button *button = acpi_driver_data(device);
struct acpi_device *device = data;
struct acpi_button *button;
if (event != ACPI_BUTTON_NOTIFY_STATUS) {
acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
event);
return;
}
button = acpi_driver_data(device);
if (!button->lid_state_initialized)
return;
acpi_lid_update_state(device, true);
}
static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_device *device = data;
struct acpi_button *button;
struct input_dev *input;
int keycode;
switch (event) {
case ACPI_FIXED_HARDWARE_EVENT:
event = ACPI_BUTTON_NOTIFY_STATUS;
fallthrough;
case ACPI_BUTTON_NOTIFY_STATUS:
input = button->input;
if (button->type == ACPI_BUTTON_TYPE_LID) {
if (button->lid_state_initialized)
acpi_lid_update_state(device, true);
} else {
int keycode;
acpi_pm_wakeup_event(&device->dev);
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);
acpi_bus_generate_netlink_event(
device->pnp.device_class,
dev_name(&device->dev),
event, ++button->pushed);
}
break;
default:
if (event != ACPI_BUTTON_NOTIFY_STATUS) {
acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
event);
break;
return;
}
acpi_pm_wakeup_event(&device->dev);
button = acpi_driver_data(device);
if (button->suspended)
return;
input = button->input;
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);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev),
event, ++button->pushed);
}
static void acpi_button_notify_run(void *data)
{
acpi_button_notify(NULL, ACPI_BUTTON_NOTIFY_STATUS, data);
}
static u32 acpi_button_event(void *data)
{
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_button_notify_run, data);
return ACPI_INTERRUPT_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
......@@ -480,11 +507,13 @@ static int acpi_lid_input_open(struct input_dev *input)
static int acpi_button_add(struct acpi_device *device)
{
acpi_notify_handler handler;
struct acpi_button *button;
struct input_dev *input;
const char *hid = acpi_device_hid(device);
acpi_status status;
char *name, *class;
int error;
int error = 0;
if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
......@@ -508,17 +537,20 @@ static int acpi_button_add(struct acpi_device *device)
if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
!strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWER;
handler = acpi_button_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
} else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
!strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
handler = acpi_button_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
} else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
handler = acpi_lid_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
......@@ -526,12 +558,15 @@ static int acpi_button_add(struct acpi_device *device)
} else {
pr_info("Unsupported hid [%s]\n", hid);
error = -ENODEV;
goto err_free_input;
}
error = acpi_button_add_fs(device);
if (error)
goto err_free_input;
if (!error)
error = acpi_button_add_fs(device);
if (error) {
input_free_device(input);
goto err_free_button;
}
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
......@@ -559,6 +594,29 @@ static int acpi_button_add(struct acpi_device *device)
error = input_register_device(input);
if (error)
goto err_remove_fs;
switch (device->device_type) {
case ACPI_BUS_TYPE_POWER_BUTTON:
status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_button_event,
device);
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
acpi_button_event,
device);
break;
default:
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY, handler,
device);
break;
}
if (ACPI_FAILURE(status)) {
error = -ENODEV;
goto err_input_unregister;
}
if (button->type == ACPI_BUTTON_TYPE_LID) {
/*
* This assumes there's only one lid device, or if there are
......@@ -571,11 +629,11 @@ static int acpi_button_add(struct acpi_device *device)
pr_info("%s [%s]\n", name, acpi_device_bid(device));
return 0;
err_remove_fs:
err_input_unregister:
input_unregister_device(input);
err_remove_fs:
acpi_button_remove_fs(device);
err_free_input:
input_free_device(input);
err_free_button:
err_free_button:
kfree(button);
return error;
}
......@@ -584,6 +642,24 @@ static void acpi_button_remove(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
switch (device->device_type) {
case ACPI_BUS_TYPE_POWER_BUTTON:
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_button_event);
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
acpi_button_event);
break;
default:
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
button->type == ACPI_BUTTON_TYPE_LID ?
acpi_lid_notify :
acpi_button_notify);
break;
}
acpi_os_wait_events_complete();
acpi_button_remove_fs(device);
input_unregister_device(button->input);
kfree(button);
......
......@@ -662,21 +662,6 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt)
ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id());
/*
* Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
* changes to always trigger a GPE interrupt.
*
* GPE STS is a W1C register, which means:
*
* 1. Software can clear it without worrying about clearing the other
* GPEs' STS bits when the hardware sets them in parallel.
*
* 2. As long as software can ensure only clearing it when it is set,
* hardware won't set it in parallel.
*/
if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec))
acpi_clear_gpe(NULL, ec->gpe);
status = acpi_ec_read_status(ec);
/*
......@@ -1287,6 +1272,22 @@ static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
unsigned long flags;
spin_lock_irqsave(&ec->lock, flags);
/*
* Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
* changes to always trigger a GPE interrupt.
*
* GPE STS is a W1C register, which means:
*
* 1. Software can clear it without worrying about clearing the other
* GPEs' STS bits when the hardware sets them in parallel.
*
* 2. As long as software can ensure only clearing it when it is set,
* hardware won't set it in parallel.
*/
if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec))
acpi_clear_gpe(NULL, ec->gpe);
advance_transaction(ec, true);
spin_unlock_irqrestore(&ec->lock, flags);
}
......
......@@ -347,4 +347,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus);
extern struct device_attribute dev_attr_firmware_activate_noidle;
void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem);
#endif /* __NFIT_H__ */
......@@ -470,52 +470,6 @@ static const struct dmi_system_id asus_laptop[] = {
{ }
};
static const struct dmi_system_id lenovo_laptop[] = {
{
.ident = "LENOVO IdeaPad Flex 5 14ALC7",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82R9"),
},
},
{
.ident = "LENOVO IdeaPad Flex 5 16ALC7",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82RA"),
},
},
{ }
};
static const struct dmi_system_id tongfang_gm_rg[] = {
{
.ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
},
},
{ }
};
static const struct dmi_system_id maingear_laptop[] = {
{
.ident = "MAINGEAR Vector Pro 2 15",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
}
},
{
.ident = "MAINGEAR Vector Pro 2 17",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
},
},
{ }
};
static const struct dmi_system_id lg_laptop[] = {
{
.ident = "LG Electronics 17U70P",
......@@ -539,10 +493,6 @@ struct irq_override_cmp {
static const struct irq_override_cmp override_table[] = {
{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
{ lenovo_laptop, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
{ lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
{ tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
{ maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
{ lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
};
......@@ -562,16 +512,6 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
return entry->override;
}
#ifdef CONFIG_X86
/*
* IRQ override isn't needed on modern AMD Zen systems and
* this override breaks active low IRQs on AMD Ryzen 6000 and
* newer systems. Skip it.
*/
if (boot_cpu_has(X86_FEATURE_ZEN))
return false;
#endif
return true;
}
......
......@@ -2029,8 +2029,6 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
return count;
}
static bool acpi_bus_scan_second_pass;
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
struct acpi_device **adev_p)
{
......@@ -2050,10 +2048,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
return AE_OK;
/* Bail out if there are dependencies. */
if (acpi_scan_check_dep(handle, check_dep) > 0) {
acpi_bus_scan_second_pass = true;
if (acpi_scan_check_dep(handle, check_dep) > 0)
return AE_CTRL_DEPTH;
}
fallthrough;
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
......@@ -2301,6 +2297,12 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
return true;
}
static void acpi_scan_delete_dep_data(struct acpi_dep_data *dep)
{
list_del(&dep->node);
kfree(dep);
}
static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
{
struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer);
......@@ -2311,8 +2313,10 @@ static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
acpi_dev_put(adev);
}
list_del(&dep->node);
kfree(dep);
if (dep->free_when_met)
acpi_scan_delete_dep_data(dep);
else
dep->met = true;
return 0;
}
......@@ -2406,6 +2410,55 @@ struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
}
EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
static void acpi_scan_postponed_branch(acpi_handle handle)
{
struct acpi_device *adev = NULL;
if (ACPI_FAILURE(acpi_bus_check_add(handle, false, &adev)))
return;
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_check_add_2, NULL, NULL, (void **)&adev);
acpi_bus_attach(adev, NULL);
}
static void acpi_scan_postponed(void)
{
struct acpi_dep_data *dep, *tmp;
mutex_lock(&acpi_dep_list_lock);
list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
acpi_handle handle = dep->consumer;
/*
* In case there are multiple acpi_dep_list entries with the
* same consumer, skip the current entry if the consumer device
* object corresponding to it is present already.
*/
if (!acpi_fetch_acpi_dev(handle)) {
/*
* Even though the lock is released here, tmp is
* guaranteed to be valid, because none of the list
* entries following dep is marked as "free when met"
* and so they cannot be deleted.
*/
mutex_unlock(&acpi_dep_list_lock);
acpi_scan_postponed_branch(handle);
mutex_lock(&acpi_dep_list_lock);
}
if (dep->met)
acpi_scan_delete_dep_data(dep);
else
dep->free_when_met = true;
}
mutex_unlock(&acpi_dep_list_lock);
}
/**
* acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
* @handle: Root of the namespace scope to scan.
......@@ -2424,8 +2477,6 @@ int acpi_bus_scan(acpi_handle handle)
{
struct acpi_device *device = NULL;
acpi_bus_scan_second_pass = false;
/* Pass 1: Avoid enumerating devices with missing dependencies. */
if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device)))
......@@ -2438,19 +2489,9 @@ int acpi_bus_scan(acpi_handle handle)
acpi_bus_attach(device, (void *)true);
if (!acpi_bus_scan_second_pass)
return 0;
/* Pass 2: Enumerate all of the remaining devices. */
device = NULL;
if (ACPI_SUCCESS(acpi_bus_check_add(handle, false, &device)))
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_check_add_2, NULL, NULL,
(void **)&device);
acpi_bus_attach(device, NULL);
acpi_scan_postponed();
return 0;
}
......
......@@ -848,7 +848,7 @@ void __weak acpi_s2idle_setup(void)
s2idle_set_ops(&acpi_s2idle_ops);
}
static void acpi_sleep_suspend_setup(void)
static void __init acpi_sleep_suspend_setup(void)
{
bool suspend_ops_needed = false;
int i;
......
This diff is collapsed.
......@@ -19,18 +19,52 @@ static const struct acpi_device_id tiny_power_button_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids);
static int acpi_noop_add(struct acpi_device *device)
static void acpi_tiny_power_button_notify(acpi_handle handle, u32 event, void *data)
{
return 0;
kill_cad_pid(power_signal, 1);
}
static void acpi_noop_remove(struct acpi_device *device)
static void acpi_tiny_power_button_notify_run(void *not_used)
{
acpi_tiny_power_button_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, NULL);
}
static void acpi_tiny_power_button_notify(struct acpi_device *device, u32 event)
static u32 acpi_tiny_power_button_event(void *not_used)
{
kill_cad_pid(power_signal, 1);
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_tiny_power_button_notify_run, NULL);
return ACPI_INTERRUPT_HANDLED;
}
static int acpi_tiny_power_button_add(struct acpi_device *device)
{
acpi_status status;
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_tiny_power_button_event,
NULL);
} else {
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY,
acpi_tiny_power_button_notify,
NULL);
}
if (ACPI_FAILURE(status))
return -ENODEV;
return 0;
}
static void acpi_tiny_power_button_remove(struct acpi_device *device)
{
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
acpi_tiny_power_button_event);
} else {
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
acpi_tiny_power_button_notify);
}
acpi_os_wait_events_complete();
}
static struct acpi_driver acpi_tiny_power_button_driver = {
......@@ -38,9 +72,8 @@ static struct acpi_driver acpi_tiny_power_button_driver = {
.class = "tiny-power-button",
.ids = tiny_power_button_device_ids,
.ops = {
.add = acpi_noop_add,
.remove = acpi_noop_remove,
.notify = acpi_tiny_power_button_notify,
.add = acpi_tiny_power_button_add,
.remove = acpi_tiny_power_button_remove,
},
};
......
......@@ -470,6 +470,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
},
},
{
.callback = video_detect_force_native,
/* Lenovo ThinkPad X131e (3371 AMD version) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "3371"),
},
},
{
.callback = video_detect_force_native,
/* Apple iMac11,3 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "iMac11,3"),
},
},
{
/* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
.callback = video_detect_force_native,
......@@ -512,6 +528,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
},
},
{
.callback = video_detect_force_native,
/* Dell Studio 1569 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1569"),
},
},
{
.callback = video_detect_force_native,
/* Acer Aspire 3830TG */
......@@ -828,6 +852,27 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto
if (native_available)
return acpi_backlight_native;
/*
* The vendor specific BIOS interfaces are only necessary for
* laptops from before ~2008.
*
* For laptops from ~2008 till ~2023 this point is never reached
* because on those (video_caps & ACPI_VIDEO_BACKLIGHT) above is true.
*
* Laptops from after ~2023 no longer support ACPI_VIDEO_BACKLIGHT,
* if this point is reached on those, this likely means that
* the GPU kms driver which sets native_available has not loaded yet.
*
* Returning acpi_backlight_vendor in this case is known to sometimes
* cause a non working vendor specific /sys/class/backlight device to
* get registered.
*
* Return acpi_backlight_none on laptops with ACPI tables written
* for Windows 8 (laptops from after ~2012) to avoid this problem.
*/
if (acpi_osi_is_win8())
return acpi_backlight_none;
/* No ACPI video/native (old hw), use vendor specific fw methods. */
return acpi_backlight_vendor;
}
......
......@@ -485,11 +485,11 @@ int acpi_s2idle_prepare_late(void)
ACPI_LPS0_ENTRY,
lps0_dsm_func_mask, lps0_dsm_guid);
if (lps0_dsm_func_mask_microsoft > 0) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* modern standby entry */
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
}
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
......@@ -524,11 +524,6 @@ void acpi_s2idle_restore_early(void)
if (handler->restore)
handler->restore();
/* Modern standby exit */
if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* LPS0 exit */
if (lps0_dsm_func_mask > 0)
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
......@@ -539,6 +534,11 @@ void acpi_s2idle_restore_early(void)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* Modern standby exit */
if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* Screen on */
if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
......
......@@ -259,10 +259,11 @@ bool force_storage_d3(void)
* drivers/platform/x86/x86-android-tablets.c kernel module.
*/
#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0)
#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2)
#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3)
#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(4)
#define ACPI_QUIRK_UART1_SKIP BIT(1)
#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2)
#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3)
#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4)
#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5)
static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
/*
......@@ -319,6 +320,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
......@@ -365,7 +367,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
/* Nextbook Ares 8 */
/* Nextbook Ares 8 (BYT version)*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
......@@ -374,6 +376,16 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
/* Nextbook Ares 8A (CHT version)*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
DMI_MATCH(DMI_BIOS_VERSION, "M882"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
/* Whitelabel (sold as various brands) TM800A550L */
.matches = {
......@@ -392,6 +404,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
{ "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
{ "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
......@@ -438,6 +451,9 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
if (dmi_id)
quirks = (unsigned long)dmi_id->driver_data;
if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1)
*skip = true;
if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
if (uid == 1)
return -ENODEV; /* Create tty cdev instead of serdev */
......
......@@ -289,6 +289,8 @@ struct acpi_dep_data {
acpi_handle supplier;
acpi_handle consumer;
bool honor_dep;
bool met;
bool free_when_met;
};
/* Performance Management */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment