whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit 58a0228707870c8330917f919804986855443a19
parent 12dd08fa954fb7c327382ead3bb9ac861f9b9b69
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Tue, 23 Oct 2018 10:33:16 +0100

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

Pull ACPI updates from Rafael Wysocki:
 "These fix ACPICA issues related to the handling of module-level AML,
  fix an ordering issue during ACPI initialization, update ACPICA to
  upstream revision 20181003 (including fixes mostly), fix issues with
  system-wide suspend/resume related to the ACPI driver for Intel SoCs
  (LPSS), fix device enumeration issues on boards with Dollar Cove or
  Whiskey Cove Intel PMICs, prevent ACPICA from calling ktime_get() in
  unsuitable conditions, update a few drivers and clean up some code in
  several places.

  Specifics:

   - Fix ACPICA issues related to the handling of module-level AML and
     make the ACPI initialization code parse ECDT before loading the
     definition block tables (Erik Schmauss).

   - Update ACPICA to upstream revision 20181003 including fixes related
     to the ill-defined "generic serial bus" and the handling of the
     _REG object (Bob Moore).

   - Fix some issues with system-wide suspend/resume on Intel BYT/CHT
     related to the handling of I2C controllers in the ACPI LPSS driver
     for Intel SoCs (Hans de Goede).

   - Modify the ACPI namespace scanning code to enumerate INT33FE HID
     devices as platform devices with I2C resources to avoid device
     enumeration problems on boards with Dollar Cove or Whiskey Cove
     Intel PMICs (Hans de Goede).

   - Prevent ACPICA from using ktime_get() during early resume from
     system-wide suspend before resuming the timekeeping which generally
     is unsafe and triggers a warning from the timekeeping code (Bart
     Van Assche).

   - Add low-level real time clock support to the ACPI Time and Aalarm
     Device (TAD) driver (Rafael Wysocki).

   - Fix the ACPI SBS driver to avoid GPE storms on MacBook Pro and
     Oopses when removing modules (Ronald Tschalär).

   - Fix the ACPI PPTT parsing code to handle architecturally unknown
     cache types properly (Jeffrey Hugo).

   - Fix initialization issue in the ACPI processor driver (Dou Liyang).

   - Clean up the code in several places (Andy Shevchenko, Bartlomiej
     Zolnierkiewicz, David Arcari, zhong jiang)"

* tag 'acpi-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (33 commits)
  ACPI / scan: Create platform device for INT33FE ACPI nodes
  ACPI / OSL: Use 'jiffies' as the time bassis for acpi_os_get_timer()
  ACPI: probe ECDT before loading AML tables regardless of module-level code flag
  ACPICA: Remove acpi_gbl_group_module_level_code and only use acpi_gbl_execute_tables_as_methods instead
  ACPICA: AML Parser: fix parse loop to correctly skip erroneous extended opcodes
  ACPICA: AML interpreter: add region addresses in global list during initialization
  ACPI: TAD: Add low-level support for real time capability
  ACPI: remove redundant 'default n' from Kconfig
  ACPI / SBS: Fix rare oops when removing modules
  ACPI / SBS: Fix GPE storm on recent MacBookPro's
  ACPI/PPTT: Handle architecturally unknown cache types
  drivers: base: cacheinfo: Do not populate sysfs for unknown cache types
  ACPICA: Update version to 20181003
  ACPICA: Never run _REG on system_memory and system_IO
  ACPICA: Split large interpreter file
  ACPICA: Update for field unit access
  ACPICA: Rename some of the Field Attribute defines
  ACPICA: Update for generic_serial_bus and attrib_raw_process_bytes protocol
  ACPI / processor: Fix the return value of acpi_processor_ids_walk()
  ACPI / LPSS: Resume BYT/CHT I2C controllers from resume_noirq
  ...

Diffstat:
Mdrivers/acpi/Kconfig | 6------
Mdrivers/acpi/acpi_lpss.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mdrivers/acpi/acpi_processor.c | 7++++---
Mdrivers/acpi/acpi_tad.c | 201+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/acpi/acpica/Makefile | 1+
Mdrivers/acpi/acpica/acevents.h | 2++
Mdrivers/acpi/acpica/acinterp.h | 23+++++++++++++++++++++++
Mdrivers/acpi/acpica/aclocal.h | 2+-
Mdrivers/acpi/acpica/amlcode.h | 10+++++-----
Mdrivers/acpi/acpica/dsopcode.c | 4++++
Mdrivers/acpi/acpica/evregion.c | 17+++++++++++++++--
Mdrivers/acpi/acpica/evrgnini.c | 6+-----
Mdrivers/acpi/acpica/evxfregn.c | 1-
Mdrivers/acpi/acpica/exfield.c | 326+++++++++++++++++--------------------------------------------------------------
Adrivers/acpi/acpica/exserial.c | 360+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/acpi/acpica/psloop.c | 16++++++++++++++--
Mdrivers/acpi/acpica/tbxfload.c | 3+--
Mdrivers/acpi/bus.c | 44++++++++++++++++----------------------------
Mdrivers/acpi/custom_method.c | 3+--
Mdrivers/acpi/glue.c | 2+-
Mdrivers/acpi/osl.c | 16++++++++++------
Mdrivers/acpi/pmic/intel_pmic_bxtwc.c | 12++----------
Mdrivers/acpi/pmic/intel_pmic_chtdc_ti.c | 1+
Mdrivers/acpi/pmic/intel_pmic_chtwc.c | 10+---------
Mdrivers/acpi/pmic/intel_pmic_crc.c | 16++++------------
Mdrivers/acpi/pmic/intel_pmic_xpower.c | 16++++------------
Mdrivers/acpi/pmic/tps68470_pmic.c | 2+-
Mdrivers/acpi/pptt.c | 33+++++++++++++--------------------
Mdrivers/acpi/sbs.c | 8++++++--
Mdrivers/acpi/sbshc.c | 2++
Mdrivers/acpi/scan.c | 1+
Mdrivers/acpi/x86/apple.c | 4++--
Mdrivers/base/cacheinfo.c | 2++
Mdrivers/mailbox/pcc.c | 7+++++--
Mdrivers/platform/x86/intel_cht_int33fe.c | 24+++++++++---------------
Minclude/acpi/acconfig.h | 17+++++++++++++----
Minclude/acpi/acexcep.h | 9+++++++--
Minclude/acpi/acpixf.h | 9+--------
Minclude/linux/platform_device.h | 1+
39 files changed, 908 insertions(+), 434 deletions(-)

diff --git 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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); } diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c @@ -615,6 +615,8 @@ static int cache_add_dev(unsigned int cpu) this_leaf = this_cpu_ci->info_list + i; if (this_leaf->disable_sysfs) continue; + if (this_leaf->type == CACHE_TYPE_NOCACHE) + break; cache_groups = cache_get_attribute_groups(this_leaf); ci_dev = cpu_device_create(parent, this_leaf, cache_groups, "index%1u", i); diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c @@ -461,8 +461,11 @@ static int __init acpi_pcc_probe(void) count = acpi_table_parse_entries_array(ACPI_SIG_PCCT, sizeof(struct acpi_table_pcct), proc, ACPI_PCCT_TYPE_RESERVED, MAX_PCC_SUBSPACES); - if (count == 0 || count > MAX_PCC_SUBSPACES) { - pr_warn("Invalid PCCT: %d PCC subspaces\n", count); + if (count <= 0 || count > MAX_PCC_SUBSPACES) { + if (count < 0) + pr_warn("Error parsing PCC subspaces from PCCT\n"); + else + pr_warn("Invalid PCCT: %d PCC subspaces\n", count); return -EINVAL; } diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c @@ -24,6 +24,7 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -88,9 +89,9 @@ static const struct property_entry fusb302_props[] = { { } }; -static int cht_int33fe_probe(struct i2c_client *client) +static int cht_int33fe_probe(struct platform_device *pdev) { - struct device *dev = &client->dev; + struct device *dev = &pdev->dev; struct i2c_board_info board_info; struct cht_int33fe_data *data; struct i2c_client *max17047; @@ -206,7 +207,7 @@ static int cht_int33fe_probe(struct i2c_client *client) if (!data->pi3usb30532) goto out_unregister_fusb302; - i2c_set_clientdata(client, data); + platform_set_drvdata(pdev, data); return 0; @@ -224,9 +225,9 @@ out_unregister_max17047: return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ } -static int cht_int33fe_remove(struct i2c_client *i2c) +static int cht_int33fe_remove(struct platform_device *pdev) { - struct cht_int33fe_data *data = i2c_get_clientdata(i2c); + struct cht_int33fe_data *data = platform_get_drvdata(pdev); i2c_unregister_device(data->pi3usb30532); i2c_unregister_device(data->fusb302); @@ -240,29 +241,22 @@ static int cht_int33fe_remove(struct i2c_client *i2c) return 0; } -static const struct i2c_device_id cht_int33fe_i2c_id[] = { - { } -}; -MODULE_DEVICE_TABLE(i2c, cht_int33fe_i2c_id); - static const struct acpi_device_id cht_int33fe_acpi_ids[] = { { "INT33FE", }, { } }; MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids); -static struct i2c_driver cht_int33fe_driver = { +static struct platform_driver cht_int33fe_driver = { .driver = { .name = "Intel Cherry Trail ACPI INT33FE driver", .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), }, - .probe_new = cht_int33fe_probe, + .probe = cht_int33fe_probe, .remove = cht_int33fe_remove, - .id_table = cht_int33fe_i2c_id, - .disable_i2c_core_irq_mapping = true, }; -module_i2c_driver(cht_int33fe_driver); +module_platform_driver(cht_int33fe_driver); MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver"); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h @@ -173,11 +173,20 @@ #define ACPI_RSDP_CHECKSUM_LENGTH 20 #define ACPI_RSDP_XCHECKSUM_LENGTH 36 -/* SMBus, GSBus and IPMI bidirectional buffer size */ +/* + * SMBus, GSBus and IPMI buffer sizes. All have a 2-byte header, + * containing both Status and Length. + */ +#define ACPI_SERIAL_HEADER_SIZE 2 /* Common for below. Status and Length fields */ + +#define ACPI_SMBUS_DATA_SIZE 32 +#define ACPI_SMBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_SMBUS_DATA_SIZE + +#define ACPI_IPMI_DATA_SIZE 64 +#define ACPI_IPMI_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_IPMI_DATA_SIZE -#define ACPI_SMBUS_BUFFER_SIZE 34 -#define ACPI_GSBUS_BUFFER_SIZE 34 -#define ACPI_IPMI_BUFFER_SIZE 66 +#define ACPI_MAX_GSBUS_DATA_SIZE 255 +#define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE /* _sx_d and _sx_w control methods */ diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h @@ -171,8 +171,10 @@ struct acpi_exception_info { #define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021) #define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022) #define AE_AML_TARGET_TYPE EXCEP_AML (0x0023) +#define AE_AML_PROTOCOL EXCEP_AML (0x0024) +#define AE_AML_BUFFER_LENGTH EXCEP_AML (0x0025) -#define AE_CODE_AML_MAX 0x0023 +#define AE_CODE_AML_MAX 0x0025 /* * Internal exceptions used for control @@ -347,7 +349,10 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = { EXCEP_TXT("AE_AML_UNINITIALIZED_NODE", "A namespace node is uninitialized or unresolved"), EXCEP_TXT("AE_AML_TARGET_TYPE", - "A target operand of an incorrect type was encountered") + "A target operand of an incorrect type was encountered"), + EXCEP_TXT("AE_AML_PROTOCOL", "Violation of a fixed ACPI protocol"), + EXCEP_TXT("AE_AML_BUFFER_LENGTH", + "The length of the buffer is invalid/incorrect") }; static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = { diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h @@ -12,7 +12,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20180810 +#define ACPI_CA_VERSION 0x20181003 #include <acpi/acconfig.h> #include <acpi/actypes.h> @@ -157,13 +157,6 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE); /* - * Optionally support group module level code. - * NOTE, this is essentially obsolete and will be removed soon - * (01/2018). - */ -ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE); - -/* * Optionally support module level code by parsing an entire table as * a method as it is loaded. Default is TRUE. * NOTE, this is essentially obsolete and will be removed soon diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h @@ -40,6 +40,7 @@ struct platform_device { #define platform_get_device_id(pdev) ((pdev)->id_entry) +#define dev_is_platform(dev) ((dev)->bus == &platform_bus_type) #define to_platform_device(x) container_of((x), struct platform_device, dev) extern int platform_device_register(struct platform_device *);