diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-04-19 04:28:28 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-04-19 04:28:28 +0900 |
commit | 5614e7725856ea383f458377980298111439e0fb (patch) | |
tree | 82560034c3a17ee18073420406ba1228935e2967 /drivers/firmware/qemu_fw_cfg.c | |
parent | 522566376a3f8373fbd5ff75bb8a7a2da701c1a7 (diff) | |
parent | c3b46c73264b03000d1e18b22f5caf63332547c9 (diff) | |
download | lwn-5614e7725856ea383f458377980298111439e0fb.tar.gz lwn-5614e7725856ea383f458377980298111439e0fb.zip |
Merge 4.6-rc4 into driver-core-next
We want those fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/firmware/qemu_fw_cfg.c')
-rw-r--r-- | drivers/firmware/qemu_fw_cfg.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 7bba76c0206c..d999fe3b1de6 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -77,12 +77,28 @@ static inline u16 fw_cfg_sel_endianness(u16 key) static inline void fw_cfg_read_blob(u16 key, void *buf, loff_t pos, size_t count) { + u32 glk; + acpi_status status; + + /* If we have ACPI, ensure mutual exclusion against any potential + * device access by the firmware, e.g. via AML methods: + */ + status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk); + if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) { + /* Should never get here */ + WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n"); + memset(buf, 0, count); + return; + } + mutex_lock(&fw_cfg_dev_lock); iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl); while (pos-- > 0) ioread8(fw_cfg_reg_data); ioread8_rep(fw_cfg_reg_data, buf, count); mutex_unlock(&fw_cfg_dev_lock); + + acpi_release_global_lock(glk); } /* clean up fw_cfg device i/o */ @@ -725,12 +741,18 @@ device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR); static int __init fw_cfg_sysfs_init(void) { + int ret; + /* create /sys/firmware/qemu_fw_cfg/ top level directory */ fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj); if (!fw_cfg_top_ko) return -ENOMEM; - return platform_driver_register(&fw_cfg_sysfs_driver); + ret = platform_driver_register(&fw_cfg_sysfs_driver); + if (ret) + fw_cfg_kobj_cleanup(fw_cfg_top_ko); + + return ret; } static void __exit fw_cfg_sysfs_exit(void) |