diff options
Diffstat (limited to 'drivers/acpi')
32 files changed, 870 insertions, 403 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index dd1eea90f67f..9705fc986da9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -138,7 +138,6 @@ config ACPI_REV_OVERRIDE_POSSIBLE config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" - default n help Say N to disable Embedded Controller /sys/kernel/debug interface @@ -283,7 +282,6 @@ config ACPI_PROCESSOR config ACPI_IPMI tristate "IPMI" depends on IPMI_HANDLER - default n help This driver enables the ACPI to access the BMC controller. And it uses the IPMI request/response message to communicate with BMC @@ -361,7 +359,6 @@ config ACPI_TABLE_UPGRADE config ACPI_DEBUG bool "Debug Statements" - default n help The ACPI subsystem can produce debug output. Saying Y enables this output and increases the kernel size by around 50K. @@ -374,7 +371,6 @@ config ACPI_DEBUG config ACPI_PCI_SLOT bool "PCI slot detection driver" depends on SYSFS - default n help This driver creates entries in /sys/bus/pci/slots/ for all PCI slots in the system. This can help correlate PCI bus addresses, @@ -436,7 +432,6 @@ config ACPI_HED config ACPI_CUSTOM_METHOD tristate "Allow ACPI methods to be inserted/replaced at run time" depends on DEBUG_FS - default n help This debug facility allows ACPI AML methods to be inserted and/or replaced without rebooting the system. For details refer to: @@ -481,7 +476,6 @@ config ACPI_EXTLOG tristate "Extended Error Log support" depends on X86_MCE && X86_LOCAL_APIC && EDAC select UEFI_CPER - default n help Certain usages such as Predictive Failure Analysis (PFA) require more information about the error than what can be described in diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index bf64cfa30feb..10adb8cb3a3f 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -16,6 +16,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/mutex.h> +#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/platform_data/clk-lpss.h> #include <linux/platform_data/x86/pmc_atom.h> @@ -83,6 +84,7 @@ struct lpss_device_desc { size_t prv_size_override; struct property_entry *properties; void (*setup)(struct lpss_private_data *pdata); + bool resume_from_noirq; }; static const struct lpss_device_desc lpss_dma_desc = { @@ -99,6 +101,9 @@ struct lpss_private_data { u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; }; +/* Devices which need to be in D3 before lpss_iosf_enter_d3_state() proceeds */ +static u32 pmc_atom_d3_mask = 0xfe000ffe; + /* LPSS run time quirks */ static unsigned int lpss_quirks; @@ -175,6 +180,21 @@ static void byt_pwm_setup(struct lpss_private_data *pdata) static void byt_i2c_setup(struct lpss_private_data *pdata) { + const char *uid_str = acpi_device_uid(pdata->adev); + acpi_handle handle = pdata->adev->handle; + unsigned long long shared_host = 0; + acpi_status status; + long uid = 0; + + /* Expected to always be true, but better safe then sorry */ + if (uid_str) + uid = simple_strtol(uid_str, NULL, 10); + + /* Detect I2C bus shared with PUNIT and ignore its d3 status */ + status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); + if (ACPI_SUCCESS(status) && shared_host && uid) + pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1)); + lpss_deassert_reset(pdata); if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset)) @@ -274,12 +294,14 @@ static const struct lpss_device_desc byt_i2c_dev_desc = { .flags = LPSS_CLK | LPSS_SAVE_CTX, .prv_offset = 0x800, .setup = byt_i2c_setup, + .resume_from_noirq = true, }; static const struct lpss_device_desc bsw_i2c_dev_desc = { .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, .prv_offset = 0x800, .setup = byt_i2c_setup, + .resume_from_noirq = true, }; static const struct lpss_device_desc bsw_spi_dev_desc = { @@ -327,9 +349,11 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33FC", }, /* Braswell LPSS devices */ + { "80862286", LPSS_ADDR(lpss_dma_desc) }, { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) }, { "8086228A", LPSS_ADDR(bsw_uart_dev_desc) }, { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) }, + { "808622C0", LPSS_ADDR(lpss_dma_desc) }, { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) }, /* Broadwell LPSS devices */ @@ -451,26 +475,35 @@ struct lpss_device_links { */ static const struct lpss_device_links lpss_device_links[] = { {"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME}, + {"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, + {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, }; -static bool hid_uid_match(const char *hid1, const char *uid1, +static bool hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2) { - return !strcmp(hid1, hid2) && uid1 && uid2 && !strcmp(uid1, uid2); + const char *hid1 = acpi_device_hid(adev); + const char *uid1 = acpi_device_uid(adev); + + if (strcmp(hid1, hid2)) + return false; + + if (!uid2) + return true; + + return uid1 && !strcmp(uid1, uid2); } static bool acpi_lpss_is_supplier(struct acpi_device *adev, const struct lpss_device_links *link) { - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), - link->supplier_hid, link->supplier_uid); + return hid_uid_match(adev, link->supplier_hid, link->supplier_uid); } static bool acpi_lpss_is_consumer(struct acpi_device *adev, const struct lpss_device_links *link) { - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), - link->consumer_hid, link->consumer_uid); + return hid_uid_match(adev, link->consumer_hid, link->consumer_uid); } struct hid_uid { @@ -486,18 +519,23 @@ static int match_hid_uid(struct device *dev, void *data) if (!adev) return 0; - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), - id->hid, id->uid); + return hid_uid_match(adev, id->hid, id->uid); } static struct device *acpi_lpss_find_device(const char *hid, const char *uid) { + struct device *dev; + struct hid_uid data = { .hid = hid, .uid = uid, }; - return bus_find_device(&platform_bus_type, NULL, &data, match_hid_uid); + dev = bus_find_device(&platform_bus_type, NULL, &data, match_hid_uid); + if (dev) + return dev; + + return bus_find_device(&pci_bus_type, NULL, &data, match_hid_uid); } static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle) @@ -892,7 +930,7 @@ static void lpss_iosf_enter_d3_state(void) * Here we read the values related to LPSS power island, i.e. LPSS * devices, excluding both LPSS DMA controllers, along with SCC domain. */ - u32 func_dis, d3_sts_0, pmc_status, pmc_mask = 0xfe000ffe; + u32 func_dis, d3_sts_0, pmc_status; int ret; ret = pmc_atom_read(PMC_FUNC_DIS, &func_dis); @@ -910,7 +948,7 @@ static void lpss_iosf_enter_d3_state(void) * Shutdown both LPSS DMA controllers if and only if all other devices * are already in D3hot. */ - pmc_status = (~(d3_sts_0 | func_dis)) & pmc_mask; + pmc_status = (~(d3_sts_0 | func_dis)) & pmc_atom_d3_mask; if (pmc_status) goto exit; @@ -1004,7 +1042,7 @@ static int acpi_lpss_resume(struct device *dev) } #ifdef CONFIG_PM_SLEEP -static int acpi_lpss_suspend_late(struct device *dev) +static int acpi_lpss_do_suspend_late(struct device *dev) { int ret; @@ -1015,12 +1053,62 @@ static int acpi_lpss_suspend_late(struct device *dev) return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); } -static int acpi_lpss_resume_early(struct device *dev) +static int acpi_lpss_suspend_late(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + return acpi_lpss_do_suspend_late(dev); +} + +static int acpi_lpss_suspend_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + if (pdata->dev_desc->resume_from_noirq) { + ret = acpi_lpss_do_suspend_late(dev); + if (ret) + return ret; + } + + return acpi_subsys_suspend_noirq(dev); +} + +static int acpi_lpss_do_resume_early(struct device *dev) { int ret = acpi_lpss_resume(dev); return ret ? ret : pm_generic_resume_early(dev); } + +static int acpi_lpss_resume_early(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + return acpi_lpss_do_resume_early(dev); +} + +static int acpi_lpss_resume_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + ret = acpi_subsys_resume_noirq(dev); + if (ret) + return ret; + + if (!dev_pm_may_skip_resume(dev) && pdata->dev_desc->resume_from_noirq) + ret = acpi_lpss_do_resume_early(dev); + + return ret; +} + #endif /* CONFIG_PM_SLEEP */ static int acpi_lpss_runtime_suspend(struct device *dev) @@ -1050,8 +1138,8 @@ static struct dev_pm_domain acpi_lpss_pm_domain = { .complete = acpi_subsys_complete, .suspend = acpi_subsys_suspend, .suspend_late = acpi_lpss_suspend_late, - .suspend_noirq = acpi_subsys_suspend_noirq, - .resume_noirq = acpi_subsys_resume_noirq, + .suspend_noirq = acpi_lpss_suspend_noirq, + .resume_noirq = acpi_lpss_resume_noirq, .resume_early = acpi_lpss_resume_early, .freeze = acpi_subsys_freeze, .freeze_late = acpi_subsys_freeze_late, diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 449d86d39965..fc447410ae4d 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -643,7 +643,7 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, status = acpi_get_type(handle, &acpi_type); if (ACPI_FAILURE(status)) - return false; + return status; switch (acpi_type) { case ACPI_TYPE_PROCESSOR: @@ -663,11 +663,12 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, } processor_validated_ids_update(uid); - return true; + return AE_OK; err: + /* Exit on error, but don't abort the namespace walk */ acpi_handle_info(handle, "Invalid processor object\n"); - return false; + return AE_OK; } diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c index e99c4ed7e677..33a4bcdaa4d7 100644 --- a/drivers/acpi/acpi_tad.c +++ b/drivers/acpi/acpi_tad.c @@ -52,6 +52,201 @@ struct acpi_tad_driver_data { u32 capabilities; }; +struct acpi_tad_rt { + u16 year; /* 1900 - 9999 */ + u8 month; /* 1 - 12 */ + u8 day; /* 1 - 31 */ + u8 hour; /* 0 - 23 */ + u8 minute; /* 0 - 59 */ + u8 second; /* 0 - 59 */ + u8 valid; /* 0 (failed) or 1 (success) for reads, 0 for writes */ + u16 msec; /* 1 - 1000 */ + s16 tz; /* -1440 to 1440 or 2047 (unspecified) */ + u8 daylight; + u8 padding[3]; /* must be 0 */ +} __packed; + +static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) +{ + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[] = { + { .type = ACPI_TYPE_BUFFER, }, + }; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + unsigned long long retval; + acpi_status status; + + if (rt->year < 1900 || rt->year > 9999 || + rt->month < 1 || rt->month > 12 || + rt->hour > 23 || rt->minute > 59 || rt->second > 59 || + rt->tz < -1440 || (rt->tz > 1440 && rt->tz != 2047) || + rt->daylight > 3) + return -ERANGE; + + args[0].buffer.pointer = (u8 *)rt; + args[0].buffer.length = sizeof(*rt); + + pm_runtime_get_sync(dev); + + status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval); + + pm_runtime_put_sync(dev); + + if (ACPI_FAILURE(status) || retval) + return -EIO; + + return 0; +} + +static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt) +{ + acpi_handle handle = ACPI_HANDLE(dev); + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER }; + union acpi_object *out_obj; + struct acpi_tad_rt *data; + acpi_status status; + int ret = -EIO; + + pm_runtime_get_sync(dev); + + status = acpi_evaluate_object(handle, "_GRT", NULL, &output); + + pm_runtime_put_sync(dev); + + if (ACPI_FAILURE(status)) + goto out_free; + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) + goto out_free; + + if (out_obj->buffer.length != sizeof(*rt)) + goto out_free; + + data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); + if (!data->valid) + goto out_free; + + memcpy(rt, data, sizeof(*rt)); + ret = 0; + +out_free: + ACPI_FREE(output.pointer); + return ret; +} + +static char *acpi_tad_rt_next_field(char *s, int *val) +{ + char *p; + + p = strchr(s, ':'); + if (!p) + return NULL; + + *p = '\0'; + if (kstrtoint(s, 10, val)) + return NULL; + + return p + 1; +} + +static ssize_t time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_tad_rt rt; + char *str, *s; + int val, ret = -ENODATA; + + str = kmemdup_nul(buf, count, GFP_KERNEL); + if (!str) + return -ENOMEM; + + s = acpi_tad_rt_next_field(str, &val); + if (!s) + goto out_free; + + rt.year = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.month = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.day = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.hour = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.minute = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.second = val; + + s = acpi_tad_rt_next_field(s, &val); + if (!s) + goto out_free; + + rt.tz = val; + + if (kstrtoint(s, 10, &val)) + goto out_free; + + rt.daylight = val; + + rt.valid = 0; + rt.msec = 0; + memset(rt.padding, 0, 3); + + ret = acpi_tad_set_real_time(dev, &rt); + +out_free: + kfree(str); + return ret ? ret : count; +} + +static ssize_t time_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct acpi_tad_rt rt; + int ret; + + ret = acpi_tad_get_real_time(dev, &rt); + if (ret) + return ret; + + return sprintf(buf, "%u:%u:%u:%u:%u:%u:%d:%u\n", + rt.year, rt.month, rt.day, rt.hour, rt.minute, rt.second, + rt.tz, rt.daylight); +} + +static DEVICE_ATTR(time, S_IRUSR | S_IWUSR, time_show, time_store); + +static struct attribute *acpi_tad_time_attrs[] = { + &dev_attr_time.attr, + NULL, +}; +static const struct attribute_group acpi_tad_time_attr_group = { + .attrs = acpi_tad_time_attrs, +}; + static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, u32 value) { @@ -448,6 +643,12 @@ static int acpi_tad_probe(struct platform_device *pdev) goto fail; } + if (caps & ACPI_TAD_RT) { + ret = sysfs_create_group(&dev->kobj, &acpi_tad_time_attr_group); + if (ret) + goto fail; + } + return 0; fail: diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 71f6f2624deb..b14621da5413 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -65,6 +65,7 @@ acpi-y += \ exresnte.o \ exresolv.o \ exresop.o \ + exserial.o \ exstore.o \ exstoren.o \ exstorob.o \ diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 704bebbd35b0..b412aa909907 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -229,6 +229,8 @@ acpi_ev_default_region_setup(acpi_handle handle, acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj); +u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); + /* * evsci - SCI (System Control Interrupt) handling/dispatch */ diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 9613b0115dad..c5b2be0b6613 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -124,6 +124,9 @@ acpi_ex_trace_point(acpi_trace_event_type type, * exfield - ACPI AML (p-code) execution - field manipulation */ acpi_status +acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length); + +acpi_status acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc, u32 buffer_length, u32 * datum_count); @@ -268,6 +271,26 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info); /* + * exserial - field_unit support for serial address spaces + */ +acpi_status +acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer); + +acpi_status +acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, + union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer); + +acpi_status +acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer); + +acpi_status +acpi_ex_write_gpio(union acpi_operand_object *source_desc, + union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer); + +/* * exsystem - Interface to OS services */ acpi_status diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0f28a38a43ea..99b0da899109 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -395,9 +395,9 @@ struct acpi_simple_repair_info { /* Info for running the _REG methods */ struct acpi_reg_walk_info { - acpi_adr_space_type space_id; u32 function; u32 reg_run_count; + acpi_adr_space_type space_id; }; /***************************************************************************** diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 250dba02bab6..6c05355447c1 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -432,15 +432,15 @@ typedef enum { */ typedef enum { AML_FIELD_ATTRIB_QUICK = 0x02, - AML_FIELD_ATTRIB_SEND_RCV = 0x04, + AML_FIELD_ATTRIB_SEND_RECEIVE = 0x04, AML_FIELD_ATTRIB_BYTE = 0x06, AML_FIELD_ATTRIB_WORD = 0x08, AML_FIELD_ATTRIB_BLOCK = 0x0A, - AML_FIELD_ATTRIB_MULTIBYTE = 0x0B, - AML_FIELD_ATTRIB_WORD_CALL = 0x0C, - AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D, + AML_FIELD_ATTRIB_BYTES = 0x0B, + AML_FIELD_ATTRIB_PROCESS_CALL = 0x0C, + AML_FIELD_ATTRIB_BLOCK_PROCESS_CALL = 0x0D, AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, - AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F + AML_FIELD_ATTRIB_RAW_PROCESS_BYTES = 0x0F } AML_ACCESS_ATTRIBUTE; /* Bit fields in the AML method_flags byte */ diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index e9fb0bf3c8d2..78f9de260d5f 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -417,6 +417,10 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, ACPI_FORMAT_UINT64(obj_desc->region.address), obj_desc->region.length)); + status = acpi_ut_add_address_range(obj_desc->region.space_id, + obj_desc->region.address, + obj_desc->region.length, node); + /* Now the address and length are valid for this opregion */ obj_desc->region.flags |= AOPOBJ_DATA_VALID; diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 70c2bd169f66..49decca4e08f 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -653,6 +653,19 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, ACPI_FUNCTION_TRACE(ev_execute_reg_methods); + /* + * These address spaces do not need a call to _REG, since the ACPI + * specification defines them as: "must always be accessible". Since + * they never change state (never become unavailable), no need to ever + * call _REG on them. Also, a data_table is not a "real" address space, + * so do not call _REG. September 2018. + */ + if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) || + (space_id == ACPI_ADR_SPACE_SYSTEM_IO) || + (space_id == ACPI_ADR_SPACE_DATA_TABLE)) { + return_VOID; + } + info.space_id = space_id; info.function = function; info.reg_run_count = 0; @@ -714,8 +727,8 @@ acpi_ev_reg_run(acpi_handle obj_handle, } /* - * We only care about regions.and objects that are allowed to have address - * space handlers + * We only care about regions and objects that are allowed to have + * address space handlers */ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { return (AE_OK); diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 39284deedd88..17df5dacd43c 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -16,9 +16,6 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evrgnini") -/* Local prototypes */ -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); - /******************************************************************************* * * FUNCTION: acpi_ev_system_memory_region_setup @@ -33,7 +30,6 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); * DESCRIPTION: Setup a system_memory operation region * ******************************************************************************/ - acpi_status acpi_ev_system_memory_region_setup(acpi_handle handle, u32 function, @@ -313,7 +309,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, * ******************************************************************************/ -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) +u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) { acpi_status status; struct acpi_pnp_device_id *hid; diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 091415b14fbf..3b3a25d9f0e6 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -193,7 +193,6 @@ acpi_remove_address_space_handler(acpi_handle device, */ region_obj = handler_obj->address_space.region_list; - } /* Remove this Handler object from the list */ diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index b272c329d45d..e5798f15793a 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /****************************************************************************** * - * Module Name: exfield - ACPI AML (p-code) execution - field manipulation + * Module Name: exfield - AML execution - field_unit read/write * * Copyright (C) 2000 - 2018, Intel Corp. * @@ -16,64 +16,62 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exfield") -/* Local prototypes */ -static u32 -acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); +/* + * This table maps the various Attrib protocols to the byte transfer + * length. Used for the generic serial bus. + */ +#define ACPI_INVALID_PROTOCOL_ID 0x80 +#define ACPI_MAX_PROTOCOL_ID 0x0F +const u8 acpi_protocol_lengths[] = { + ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */ + ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */ + 0x00, /* 2 - ATTRIB_QUICK */ + ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */ + 0x01, /* 4 - ATTRIB_SEND_RECEIVE */ + ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */ + 0x01, /* 6 - ATTRIB_BYTE */ + ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */ + 0x02, /* 8 - ATTRIB_WORD */ + ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */ + 0xFF, /* A - ATTRIB_BLOCK */ + 0xFF, /* B - ATTRIB_BYTES */ + 0x02, /* C - ATTRIB_PROCESS_CALL */ + 0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */ + 0xFF, /* E - ATTRIB_RAW_BYTES */ + 0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */ +}; /******************************************************************************* * - * FUNCTION: acpi_ex_get_serial_access_length + * FUNCTION: acpi_ex_get_protocol_buffer_length * - * PARAMETERS: accessor_type - The type of the protocol indicated by region + * PARAMETERS: protocol_id - The type of the protocol indicated by region * field access attributes - * access_length - The access length of the region field + * return_length - Where the protocol byte transfer length is + * returned * - * RETURN: Decoded access length + * RETURN: Status and decoded byte transfer length * * DESCRIPTION: This routine returns the length of the generic_serial_bus * protocol bytes * ******************************************************************************/ -static u32 -acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) +acpi_status +acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length) { - u32 length; - - switch (accessor_type) { - case AML_FIELD_ATTRIB_QUICK: - - length = 0; - break; - - case AML_FIELD_ATTRIB_SEND_RCV: - case AML_FIELD_ATTRIB_BYTE: - - length = 1; - break; - - case AML_FIELD_ATTRIB_WORD: - case AML_FIELD_ATTRIB_WORD_CALL: - - length = 2; - break; - case AML_FIELD_ATTRIB_MULTIBYTE: - case AML_FIELD_ATTRIB_RAW_BYTES: - case AML_FIELD_ATTRIB_RAW_PROCESS: + if ((protocol_id > ACPI_MAX_PROTOCOL_ID) || + (acpi_protocol_lengths[protocol_id] == ACPI_INVALID_PROTOCOL_ID)) { + ACPI_ERROR((AE_INFO, + "Invalid Field/AccessAs protocol ID: 0x%4.4X", + protocol_id)); - length = access_length; - break; - - case AML_FIELD_ATTRIB_BLOCK: - case AML_FIELD_ATTRIB_BLOCK_CALL: - default: - - length = ACPI_GSBUS_BUFFER_SIZE - 2; - break; + return (AE_AML_PROTOCOL); } - return (length); + *return_length = acpi_protocol_lengths[protocol_id]; + return (AE_OK); } /******************************************************************************* @@ -98,10 +96,8 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, { acpi_status status; union acpi_operand_object *buffer_desc; - acpi_size length; void *buffer; - u32 function; - u16 accessor_type; + u32 buffer_length; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -132,60 +128,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI)) { - /* - * This is an SMBus, GSBus or IPMI read. We must create a buffer to - * hold the data and then directly access the region handler. - * - * Note: SMBus and GSBus protocol value is passed in upper 16-bits - * of Function - */ - if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS) { - length = ACPI_SMBUS_BUFFER_SIZE; - function = - ACPI_READ | (obj_desc->field.attribute << 16); - } else if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_GSBUS) { - accessor_type = obj_desc->field.attribute; - length = - acpi_ex_get_serial_access_length(accessor_type, - obj_desc->field. - access_length); - - /* - * Add additional 2 bytes for the generic_serial_bus data buffer: - * - * Status; (Byte 0 of the data buffer) - * Length; (Byte 1 of the data buffer) - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) - */ - length += 2; - function = ACPI_READ | (accessor_type << 16); - } else { /* IPMI */ - - length = ACPI_IPMI_BUFFER_SIZE; - function = ACPI_READ; - } - - buffer_desc = acpi_ut_create_buffer_object(length); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - - /* Call the region handler for the read */ - status = acpi_ex_access_region(obj_desc, 0, - ACPI_CAST_PTR(u64, - buffer_desc-> - buffer.pointer), - function); + /* SMBus, GSBus, IPMI serial */ - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - goto exit; + status = acpi_ex_read_serial_bus(obj_desc, ret_buffer_desc); + return_ACPI_STATUS(status); } /* @@ -198,14 +145,14 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, * * Note: Field.length is in bits. */ - length = + buffer_length = (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); - if (length > acpi_gbl_integer_byte_width) { + if (buffer_length > acpi_gbl_integer_byte_width) { /* Field is too large for an Integer, create a Buffer instead */ - buffer_desc = acpi_ut_create_buffer_object(length); + buffer_desc = acpi_ut_create_buffer_object(buffer_length); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -218,47 +165,24 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NO_MEMORY); } - length = acpi_gbl_integer_byte_width; + buffer_length = acpi_gbl_integer_byte_width; buffer = &buffer_desc->integer.value; } if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) { - /* - * For GPIO (general_purpose_io), the Address will be the bit offset - * from the previous Connection() operator, making it effectively a - * pin number index. The bit_length is the length of the field, which - * is thus the number of pins. - */ - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "GPIO FieldRead [FROM]: Pin %u Bits %u\n", - obj_desc->field.pin_number_index, - obj_desc->field.bit_length)); - - /* Lock entire transaction if requested */ - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + /* General Purpose I/O */ - /* Perform the write */ - - status = - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, - ACPI_READ); - - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(buffer_desc); - } else { - *ret_buffer_desc = buffer_desc; - } - return_ACPI_STATUS(status); + status = acpi_ex_read_gpio(obj_desc, buffer); + goto exit; } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", obj_desc, obj_desc->common.type, buffer, - (u32) length)); + buffer_length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", obj_desc->common_field.bit_length, @@ -271,7 +195,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Read from the field */ - status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); + status = acpi_ex_extract_from_field(obj_desc, buffer, buffer_length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); exit: @@ -304,11 +228,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, union acpi_operand_object **result_desc) { acpi_status status; - u32 length; + u32 buffer_length; void *buffer; - union acpi_operand_object *buffer_desc; - u32 function; - u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -331,130 +252,25 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS - || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_GSBUS - || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { - /* - * This is an SMBus, GSBus or IPMI write. We will bypass the entire - * field mechanism and handoff the buffer directly to the handler. - * For these address spaces, the buffer is bi-directional; on a - * write, return data is returned in the same buffer. - * - * Source must be a buffer of sufficient size: - * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or - * ACPI_IPMI_BUFFER_SIZE. - * - * Note: SMBus and GSBus protocol type is passed in upper 16-bits - * of Function - */ - if (source_desc->common.type != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, - "SMBus/IPMI/GenericSerialBus write requires " - "Buffer, found type %s", - acpi_ut_get_object_type_name(source_desc))); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS) { - length = ACPI_SMBUS_BUFFER_SIZE; - function = - ACPI_WRITE | (obj_desc->field.attribute << 16); - } else if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_GSBUS) { - accessor_type = obj_desc->field.attribute; - length = - acpi_ex_get_serial_access_length(accessor_type, - obj_desc->field. - access_length); - - /* - * Add additional 2 bytes for the generic_serial_bus data buffer: - * - * Status; (Byte 0 of the data buffer) - * Length; (Byte 1 of the data buffer) - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) - */ - length += 2; - function = ACPI_WRITE | (accessor_type << 16); - } else { /* IPMI */ - - length = ACPI_IPMI_BUFFER_SIZE; - function = ACPI_WRITE; - } - - if (source_desc->buffer.length < length) { - ACPI_ERROR((AE_INFO, - "SMBus/IPMI/GenericSerialBus write requires " - "Buffer of length %u, found length %u", - length, source_desc->buffer.length)); - - return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); - } - - /* Create the bi-directional buffer */ - - buffer_desc = acpi_ut_create_buffer_object(length); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - buffer = buffer_desc->buffer.pointer; - memcpy(buffer, source_desc->buffer.pointer, length); - - /* Lock entire transaction if requested */ + ACPI_ADR_SPACE_GPIO)) { - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + /* General Purpose I/O */ - /* - * Perform the write (returns status and perhaps data in the - * same buffer) - */ - status = - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - - *result_desc = buffer_desc; + status = acpi_ex_write_gpio(source_desc, obj_desc, result_desc); return_ACPI_STATUS(status); } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_GPIO)) { - /* - * For GPIO (general_purpose_io), we will bypass the entire field - * mechanism and handoff the bit address and bit width directly to - * the handler. The Address will be the bit offset - * from the previous Connection() operator, making it effectively a - * pin number index. The bit_length is the length of the field, which - * is thus the number of pins. - */ - if (source_desc->common.type != ACPI_TYPE_INTEGER) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", - acpi_ut_get_type_name(source_desc->common. - type), - source_desc->common.type, - (u32)source_desc->integer.value, - obj_desc->field.pin_number_index, - obj_desc->field.bit_length)); - - buffer = &source_desc->integer.value; - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + ACPI_ADR_SPACE_SMBUS + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_GSBUS + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_IPMI)) { - /* Perform the write */ + /* SMBus, GSBus, IPMI serial */ status = - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, - ACPI_WRITE); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + acpi_ex_write_serial_bus(source_desc, obj_desc, + result_desc); return_ACPI_STATUS(status); } @@ -464,23 +280,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; - length = sizeof(source_desc->integer.value); + buffer_length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: buffer = source_desc->buffer.pointer; - length = source_desc->buffer.length; + buffer_length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: buffer = source_desc->string.pointer; - length = source_desc->string.length; + buffer_length = source_desc->string.length; break; default: - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -488,7 +303,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(source_desc->common.type), - source_desc->common.type, buffer, length)); + source_desc->common.type, buffer, buffer_length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", @@ -505,8 +320,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Write to the field */ - status = acpi_ex_insert_into_field(obj_desc, buffer, length); + status = acpi_ex_insert_into_field(obj_desc, buffer, buffer_length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c new file mode 100644 index 000000000000..0d42f30e5b25 --- /dev/null +++ b/drivers/acpi/acpica/exserial.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/****************************************************************************** + * + * Module Name: exserial - field_unit support for serial address spaces + * + * Copyright (C) 2000 - 2018, Intel Corp. + * + *****************************************************************************/ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exserial") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_read_gpio + * + * PARAMETERS: obj_desc - The named field to read + * buffer - Where the return data is returnd + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a Generic Serial Bus + * field + * + ******************************************************************************/ +acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc); + + /* + * For GPIO (general_purpose_io), the Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The bit_length is the length of the field, which + * is thus the number of pins. + */ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "GPIO FieldRead [FROM]: Pin %u Bits %u\n", + obj_desc->field.pin_number_index, + obj_desc->field.bit_length)); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Perform the read */ + + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ); + + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_write_gpio + * + * PARAMETERS: source_desc - Contains data to write. Expect to be + * an Integer object. + * obj_desc - The named field + * result_desc - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a General Purpose I/O + * field. + * + ******************************************************************************/ + +acpi_status +acpi_ex_write_gpio(union acpi_operand_object *source_desc, + union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer) +{ + acpi_status status; + void *buffer; + + ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc); + + /* + * For GPIO (general_purpose_io), we will bypass the entire field + * mechanism and handoff the bit address and bit width directly to + * the handler. The Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The bit_length is the length of the field, which + * is thus the number of pins. + */ + if (source_desc->common.type != ACPI_TYPE_INTEGER) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n", + acpi_ut_get_type_name(source_desc->common.type), + source_desc->common.type, + (u32)source_desc->integer.value, + obj_desc->field.pin_number_index, + obj_desc->field.bit_length)); + + buffer = &source_desc->integer.value; + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Perform the write */ + + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_read_serial_bus + * + * PARAMETERS: obj_desc - The named field to read + * return_buffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a serial bus + * (SMBus, IPMI, or GSBus). + * + ******************************************************************************/ + +acpi_status +acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer) +{ + acpi_status status; + u32 buffer_length; + union acpi_operand_object *buffer_desc; + u32 function; + u16 accessor_type; + + ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc); + + /* + * This is an SMBus, GSBus or IPMI read. We must create a buffer to + * hold the data and then directly access the region handler. + * + * Note: SMBus and GSBus protocol value is passed in upper 16-bits + * of Function + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + switch (obj_desc->field.region_obj->region.space_id) { + case ACPI_ADR_SPACE_SMBUS: + + buffer_length = ACPI_SMBUS_BUFFER_SIZE; + function = ACPI_READ | (obj_desc->field.attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + buffer_length = ACPI_IPMI_BUFFER_SIZE; + function = ACPI_READ; + break; + + case ACPI_ADR_SPACE_GSBUS: + + accessor_type = obj_desc->field.attribute; + if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) { + ACPI_ERROR((AE_INFO, + "Invalid direct read using bidirectional write-then-read protocol")); + + return_ACPI_STATUS(AE_AML_PROTOCOL); + } + + status = + acpi_ex_get_protocol_buffer_length(accessor_type, + &buffer_length); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", + accessor_type)); + + return_ACPI_STATUS(status); + } + + /* Add header length to get the full size of the buffer */ + + buffer_length += ACPI_SERIAL_HEADER_SIZE; + function = ACPI_READ | (accessor_type << 16); + break; + + default: + return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); + } + + /* Create the local transfer buffer that is returned to the caller */ + + buffer_desc = acpi_ut_create_buffer_object(buffer_length); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Call the region handler for the write-then-read */ + + status = acpi_ex_access_region(obj_desc, 0, + ACPI_CAST_PTR(u64, + buffer_desc->buffer. + pointer), function); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + + *return_buffer = buffer_desc; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_write_serial_bus + * + * PARAMETERS: source_desc - Contains data to write + * obj_desc - The named field + * return_buffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a serial bus + * (SMBus, IPMI, GSBus). + * + ******************************************************************************/ + +acpi_status +acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, + union acpi_operand_object *obj_desc, + union acpi_operand_object **return_buffer) +{ + acpi_status status; + u32 buffer_length; + u32 data_length; + void *buffer; + union acpi_operand_object *buffer_desc; + u32 function; + u16 accessor_type; + + ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc); + + /* + * This is an SMBus, GSBus or IPMI write. We will bypass the entire + * field mechanism and handoff the buffer directly to the handler. + * For these address spaces, the buffer is bidirectional; on a + * write, return data is returned in the same buffer. + * + * Source must be a buffer of sufficient size, these are fixed size: + * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. + * + * Note: SMBus and GSBus protocol type is passed in upper 16-bits + * of Function + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + if (source_desc->common.type != ACPI_TYPE_BUFFER) { + ACPI_ERROR((AE_INFO, + "SMBus/IPMI/GenericSerialBus write requires " + "Buffer, found type %s", + acpi_ut_get_object_type_name(source_desc))); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + switch (obj_desc->field.region_obj->region.space_id) { + case ACPI_ADR_SPACE_SMBUS: + + buffer_length = ACPI_SMBUS_BUFFER_SIZE; + data_length = ACPI_SMBUS_DATA_SIZE; + function = ACPI_WRITE | (obj_desc->field.attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + buffer_length = ACPI_IPMI_BUFFER_SIZE; + data_length = ACPI_IPMI_DATA_SIZE; + function = ACPI_WRITE; + break; + + case ACPI_ADR_SPACE_GSBUS: + + accessor_type = obj_desc->field.attribute; + status = + acpi_ex_get_protocol_buffer_length(accessor_type, + &buffer_length); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", + accessor_type)); + + return_ACPI_STATUS(status); + } + + /* Add header length to get the full size of the buffer */ + + buffer_length += ACPI_SERIAL_HEADER_SIZE; + data_length = source_desc->buffer.pointer[1]; + function = ACPI_WRITE | (accessor_type << 16); + break; + + default: + return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); + } + +#if 0 + OBSOLETE ? + /* Check for possible buffer overflow */ + if (data_length > source_desc->buffer.length) { + ACPI_ERROR((AE_INFO, + "Length in buffer header (%u)(%u) is greater than " + "the physical buffer length (%u) and will overflow", + data_length, buffer_length, + source_desc->buffer.length)); + + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } +#endif + + /* Create the transfer/bidirectional/return buffer */ + + buffer_desc = acpi_ut_create_buffer_object(buffer_length); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy the input buffer data to the transfer buffer */ + + buffer = buffer_desc->buffer.pointer; + memcpy(buffer, source_desc->buffer.pointer, data_length); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* + * Perform the write (returns status and perhaps data in the + * same buffer) + */ + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + + *return_buffer = buffer_desc; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 34fc2f7476ed..0fa01c9e353e 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -147,7 +147,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, * future. Use of this option can cause problems with AML code that * depends upon in-order immediate execution of module-level code. */ - if (acpi_gbl_group_module_level_code && + if (!acpi_gbl_execute_tables_as_methods && (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) && ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { /* @@ -417,6 +417,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) union acpi_parse_object *op = NULL; /* current op */ struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; + u8 opcode_length; ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); @@ -540,8 +541,19 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) "Skip parsing opcode %s", acpi_ps_get_opcode_name (walk_state->opcode))); + + /* + * Determine the opcode length before skipping the opcode. + * An opcode can be 1 byte or 2 bytes in length. + */ + opcode_length = 1; + if ((walk_state->opcode & 0xFF00) == + AML_EXTENDED_OPCODE) { + opcode_length = 2; + } walk_state->parser_state.aml = - walk_state->aml + 1; + walk_state->aml + opcode_length; + walk_state->parser_state.aml = acpi_ps_get_next_package_end (&walk_state->parser_state); diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 2f40f71c06db..9011297552af 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -69,8 +69,7 @@ acpi_status ACPI_INIT_FUNCTION acpi_load_tables(void) "While loading namespace from ACPI tables")); } - if (acpi_gbl_execute_tables_as_methods - || !acpi_gbl_group_module_level_code) { + if (acpi_gbl_execute_tables_as_methods) { /* * If the module-level code support is enabled, initialize the objects * in the namespace that remain uninitialized. This runs the executable diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d2e29a19890d..bb3d96dea6db 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1054,15 +1054,17 @@ void __init acpi_early_init(void) goto error0; } - if (!acpi_gbl_execute_tables_as_methods && - acpi_gbl_group_module_level_code) { - status = acpi_load_tables(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to load the System Description Tables\n"); - goto error0; - } - } + /* + * ACPI 2.0 requires the EC driver to be loaded and work before + * the EC device is found in the namespace (i.e. before + * acpi_load_tables() is called). + * + * This is accomplished by looking for the ECDT table, and getting + * the EC parameters out of that. + * + * Ignore the result. Not having an ECDT is not fatal. + */ + status = acpi_ec_ecdt_probe(); #ifdef CONFIG_X86 if (!acpi_ioapic) { @@ -1133,25 +1135,11 @@ static int __init acpi_bus_init(void) acpi_os_initialize1(); - /* - * ACPI 2.0 requires the EC driver to be loaded and work before - * the EC device is found in the namespace (i.e. before - * acpi_load_tables() is called). - * - * This is accomplished by looking for the ECDT table, and getting - * the EC parameters out of that. - */ - status = acpi_ec_ecdt_probe(); - /* Ignore result. Not having an ECDT is not fatal. */ - - if (acpi_gbl_execute_tables_as_methods || - !acpi_gbl_group_module_level_code) { - status = acpi_load_tables(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to load the System Description Tables\n"); - goto error1; - } + status = acpi_load_tables(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX + "Unable to load the System Description Tables\n"); + goto error1; } status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE); diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c index e967c1173ba3..4451877f83b6 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -92,8 +92,7 @@ static int __init acpi_custom_method_init(void) static void __exit acpi_custom_method_exit(void) { - if (cm_dentry) - debugfs_remove(cm_dentry); + debugfs_remove(cm_dentry); } module_init(acpi_custom_method_init); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 3be1433853bf..12ba2bee8789 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -320,7 +320,7 @@ static int acpi_platform_notify(struct device *dev) if (!adev) goto out; - if (dev->bus == &platform_bus_type) + if (dev_is_platform(dev)) acpi_configure_pmsi_domain(dev); if (type && type->setup) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 8df9abfa947b..b48874b8e1ea 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -617,15 +617,18 @@ void acpi_os_stall(u32 us) } /* - * Support ACPI 3.0 AML Timer operand - * Returns 64-bit free-running, monotonically increasing timer - * with 100ns granularity + * Support ACPI 3.0 AML Timer operand. Returns a 64-bit free-running, + * monotonically increasing timer with 100ns granularity. Do not use + * ktime_get() to implement this function because this function may get + * called after timekeeping has been suspended. Note: calling this function + * after timekeeping has been suspended may lead to unexpected results + * because when timekeeping is suspended the jiffies counter is not + * incremented. See also timekeeping_suspend(). */ u64 acpi_os_get_timer(void) { - u64 time_ns = ktime_to_ns(ktime_get()); - do_div(time_ns, 100); - return time_ns; + return (get_jiffies_64() - INITIAL_JIFFIES) * + (ACPI_100NSEC_PER_SEC / HZ); } acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) @@ -1129,6 +1132,7 @@ void acpi_os_wait_events_complete(void) flush_workqueue(kacpid_wq); flush_workqueue(kacpi_notify_wq); } +EXPORT_SYMBOL(acpi_os_wait_events_complete); struct acpi_hp_work { struct work_struct work; diff --git a/drivers/acpi/pmic/intel_pmic_bxtwc.c b/drivers/acpi/pmic/intel_pmic_bxtwc.c index 886ac8b93cd0..bd7621edd60b 100644 --- a/drivers/acpi/pmic/intel_pmic_bxtwc.c +++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * intel_pmic_bxtwc.c - Intel BXT WhiskeyCove PMIC operation region driver + * Intel BXT WhiskeyCove PMIC operation region driver * * Copyright (C) 2015 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/init.h> diff --git a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c index f6d73a243d80..7ccd7d9660bc 100644 --- a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c +++ b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Dollar Cove TI PMIC operation region driver * Copyright (C) 2014 Intel Corporation. All rights reserved. diff --git a/drivers/acpi/pmic/intel_pmic_chtwc.c b/drivers/acpi/pmic/intel_pmic_chtwc.c index 9912422c8185..078b0448f30a 100644 --- a/drivers/acpi/pmic/intel_pmic_chtwc.c +++ b/drivers/acpi/pmic/intel_pmic_chtwc.c @@ -1,18 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Intel CHT Whiskey Cove PMIC operation region driver * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> * * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/acpi.h> diff --git a/drivers/acpi/pmic/intel_pmic_crc.c b/drivers/acpi/pmic/intel_pmic_crc.c index 22c9e374c923..a0f411a6e5ac 100644 --- a/drivers/acpi/pmic/intel_pmic_crc.c +++ b/drivers/acpi/pmic/intel_pmic_crc.c @@ -1,23 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * intel_pmic_crc.c - Intel CrystalCove PMIC operation region driver + * Intel CrystalCove PMIC operation region driver * * Copyright (C) 2014 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ -#include <linux/init.h> #include <linux/acpi.h> +#include <linux/init.h> #include <linux/mfd/intel_soc_pmic.h> -#include <linux/regmap.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include "intel_pmic.h" #define PWR_SOURCE_SELECT BIT(1) diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index 316e55174aa9..aadc86db804c 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -1,23 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * intel_pmic_xpower.c - XPower AXP288 PMIC operation region driver + * XPower AXP288 PMIC operation region driver * * Copyright (C) 2014 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ -#include <linux/init.h> #include <linux/acpi.h> +#include <linux/init.h> #include <linux/mfd/axp20x.h> -#include <linux/regmap.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include "intel_pmic.h" #define XPOWER_GPADC_LOW 0x5b diff --git a/drivers/acpi/pmic/tps68470_pmic.c b/drivers/acpi/pmic/tps68470_pmic.c index a083de507009..ebd03e472955 100644 --- a/drivers/acpi/pmic/tps68470_pmic.c +++ b/drivers/acpi/pmic/tps68470_pmic.c @@ -10,8 +10,8 @@ */ #include <linux/acpi.h> -#include <linux/mfd/tps68470.h> #include <linux/init.h> +#include <linux/mfd/tps68470.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index d1e26cb599bf..da031b1df6f5 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -338,9 +338,6 @@ static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *ta return found; } -/* total number of attributes checked by the properties code */ -#define PPTT_CHECKED_ATTRIBUTES 4 - /** * update_cache_properties() - Update cacheinfo for the given processor * @this_leaf: Kernel cache info structure being updated @@ -357,25 +354,15 @@ static void update_cache_properties(struct cacheinfo *this_leaf, struct acpi_pptt_cache *found_cache, struct acpi_pptt_processor *cpu_node) { - int valid_flags = 0; - this_leaf->fw_token = cpu_node; - if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) { + if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) this_leaf->size = found_cache->size; - valid_flags++; - } - if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID) { + if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID) this_leaf->coherency_line_size = found_cache->line_size; - valid_flags++; - } - if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID) { + if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID) this_leaf->number_of_sets = found_cache->number_of_sets; - valid_flags++; - } - if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID) { + if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID) this_leaf->ways_of_associativity = found_cache->associativity; - valid_flags++; - } if (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID) { switch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) { case ACPI_PPTT_CACHE_POLICY_WT: @@ -402,11 +389,17 @@ static void update_cache_properties(struct cacheinfo *this_leaf, } } /* - * If the above flags are valid, and the cache type is NOCACHE - * update the cache type as well. + * If cache type is NOCACHE, then the cache hasn't been specified + * via other mechanisms. Update the type if a cache type has been + * provided. + * + * Note, we assume such caches are unified based on conventional system + * design and known examples. Significant work is required elsewhere to + * fully support data/instruction only type caches which are only + * specified in PPTT. */ if (this_leaf->type == CACHE_TYPE_NOCACHE && - valid_flags == PPTT_CHECKED_ATTRIBUTES) + found_cache->flags & ACPI_PPTT_CACHE_TYPE_VALID) this_leaf->type = CACHE_TYPE_UNIFIED; } diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 295b59271189..96c5e27967f4 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -441,9 +441,13 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) /* * The spec requires that bit 4 always be 1. If it's not set, assume - * that the implementation doesn't support an SBS charger + * that the implementation doesn't support an SBS charger. + * + * And on some MacBooks a status of 0xffff is always returned, no + * matter whether the charger is plugged in or not, which is also + * wrong, so ignore the SBS charger for those too. */ - if (!((status >> 4) & 0x1)) + if (!((status >> 4) & 0x1) || status == 0xffff) return -ENODEV; sbs->charger_present = (status >> 15) & 0x1; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 7a3431018e0a..5008ead4609a 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -196,6 +196,7 @@ int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc) hc->callback = NULL; hc->context = NULL; mutex_unlock(&hc->lock); + acpi_os_wait_events_complete(); return 0; } @@ -292,6 +293,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device) hc = acpi_driver_data(device); acpi_ec_remove_query_handler(hc->ec, hc->query_bit); + acpi_os_wait_events_complete(); kfree(hc); device->driver_data = NULL; return 0; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 56676a56b3e3..bd1c59fb0e17 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1540,6 +1540,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) */ static const struct acpi_device_id i2c_multi_instantiate_ids[] = { {"BSG1160", }, + {"INT33FE", }, {} }; diff --git a/drivers/acpi/x86/apple.c b/drivers/acpi/x86/apple.c index 51b4cf9f25da..bb1984f6c9fe 100644 --- a/drivers/acpi/x86/apple.c +++ b/drivers/acpi/x86/apple.c @@ -62,7 +62,7 @@ void acpi_extract_apple_properties(struct acpi_device *adev) if (!numprops) goto out_free; - valid = kcalloc(BITS_TO_LONGS(numprops), sizeof(long), GFP_KERNEL); + valid = bitmap_zalloc(numprops, GFP_KERNEL); if (!valid) goto out_free; @@ -137,5 +137,5 @@ void acpi_extract_apple_properties(struct acpi_device *adev) out_free: ACPI_FREE(props); - kfree(valid); + bitmap_free(valid); } |