static void ec_remove_handlers(struct acpi_ec *ec)
{
---- acpi_ec_stop(ec, false);
----
if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err("failed to remove space handler\n");
clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
}
+
++++ /*
++++ * Stops handling the EC transactions after removing the operation
++++ * region handler. This is required because _REG(DISCONNECT)
++++ * invoked during the removal can result in new EC transactions.
++++ *
++++ * Flushes the EC requests and thus disables the GPE before
++++ * removing the GPE handler. This is required by the current ACPICA
++++ * GPE core. ACPICA GPE core will automatically disable a GPE when
++++ * it is indicated but there is no way to handle it. So the drivers
++++ * must disable the GPEs prior to removing the GPE handlers.
++++ */
++++ acpi_ec_stop(ec, false);
+++
if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
}
}
- ---static int acpi_ec_add(struct acpi_device *device)
+ +++static struct acpi_ec *acpi_ec_alloc(void)
{
- --- struct acpi_ec *ec = NULL;
- --- int ret;
- ---
- --- strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
- --- strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+ +++ struct acpi_ec *ec;
/* Check for boot EC */
if (boot_ec) {
first_ec = NULL;
} else {
ec = make_acpi_ec();
- --- if (!ec)
- --- return -ENOMEM;
}
+ +++ return ec;
+ +++}
+ +++
+ +++static int acpi_ec_add(struct acpi_device *device)
+ +++{
+ +++ struct acpi_ec *ec = NULL;
+ +++ int ret;
+ +++
+ +++ strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
+ +++ strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+ +++
+ +++ ec = acpi_ec_alloc();
+ +++ if (!ec)
+ +++ return -ENOMEM;
if (ec_parse_device(device->handle, 0, ec, NULL) !=
AE_CTRL_TERMINATE) {
kfree(ec);
int __init acpi_ec_dsdt_probe(void)
{
acpi_status status;
+ +++ struct acpi_ec *ec;
+ +++ int ret;
- --- if (boot_ec)
- --- return 0;
- ---
+ +++ ec = acpi_ec_alloc();
+ +++ if (!ec)
+ +++ return -ENOMEM;
/*
* Finding EC from DSDT if there is no ECDT EC available. When this
* function is invoked, ACPI tables have been fully loaded, we can
* walk namespace now.
*/
- --- boot_ec = make_acpi_ec();
- --- if (!boot_ec)
- --- return -ENOMEM;
status = acpi_get_devices(ec_device_ids[0].id,
- --- ec_parse_device, boot_ec, NULL);
- --- if (ACPI_FAILURE(status) || !boot_ec->handle)
- --- return -ENODEV;
- --- if (!ec_install_handlers(boot_ec)) {
- --- first_ec = boot_ec;
- --- return 0;
+ +++ ec_parse_device, ec, NULL);
+ +++ if (ACPI_FAILURE(status) || !ec->handle) {
+ +++ ret = -ENODEV;
+ +++ goto error;
}
- --- return -EFAULT;
+ +++ ret = ec_install_handlers(ec);
+ +++
+ +++error:
+ +++ if (ret)
+ +++ kfree(ec);
+ +++ else
+ +++ first_ec = boot_ec = ec;
+ +++ return ret;
}
#if 0
return 0;
}
+ +++/*
+ +++ * Some ECDTs contain wrong register addresses.
+ +++ * MSI MS-171F
+ +++ * https://bugzilla.kernel.org/show_bug.cgi?id=12461
+ +++ */
static int ec_correct_ecdt(const struct dmi_system_id *id)
{
pr_debug("Detected system needing ECDT address correction.\n");
}
static struct dmi_system_id ec_dmi_table[] __initdata = {
- --- {
- --- ec_correct_ecdt, "Asus L4R", {
- --- DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
- --- DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
- --- DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
- --- {
- --- ec_correct_ecdt, "Asus M6R", {
- --- DMI_MATCH(DMI_BIOS_VERSION, "0207"),
- --- DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
- --- DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
{
ec_correct_ecdt, "MSI MS-171F", {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
int __init acpi_ec_ecdt_probe(void)
{
- --- int ret = 0;
+ +++ int ret;
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
+ +++ struct acpi_ec *ec;
- --- boot_ec = make_acpi_ec();
- --- if (!boot_ec)
+ +++ ec = acpi_ec_alloc();
+ +++ if (!ec)
return -ENOMEM;
/*
* Generate a boot ec context
pr_info("EC description table is found, configuring boot EC\n");
if (EC_FLAGS_CORRECT_ECDT) {
- --- /*
- --- * Asus L4R, Asus M6R
- --- * https://bugzilla.kernel.org/show_bug.cgi?id=9399
- --- * MSI MS-171F
- --- * https://bugzilla.kernel.org/show_bug.cgi?id=12461
- --- */
- --- boot_ec->command_addr = ecdt_ptr->data.address;
- --- boot_ec->data_addr = ecdt_ptr->control.address;
+ +++ ec->command_addr = ecdt_ptr->data.address;
+ +++ ec->data_addr = ecdt_ptr->control.address;
} else {
- --- boot_ec->command_addr = ecdt_ptr->control.address;
- --- boot_ec->data_addr = ecdt_ptr->data.address;
+ +++ ec->command_addr = ecdt_ptr->control.address;
+ +++ ec->data_addr = ecdt_ptr->data.address;
}
- --- boot_ec->gpe = ecdt_ptr->gpe;
- --- boot_ec->handle = ACPI_ROOT_OBJECT;
- --- ret = ec_install_handlers(boot_ec);
- --- if (!ret)
- --- first_ec = boot_ec;
+ +++ ec->gpe = ecdt_ptr->gpe;
+ +++ ec->handle = ACPI_ROOT_OBJECT;
+ +++ ret = ec_install_handlers(ec);
error:
- --- if (ret) {
- --- kfree(boot_ec);
- --- boot_ec = NULL;
- --- }
+ +++ if (ret)
+ +++ kfree(ec);
+ +++ else
+ +++ first_ec = boot_ec = ec;
return ret;
}