From e8aabc64d7f5c8702e420c6fa478368f60718ae4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 3 Apr 2016 15:22:08 +0300 Subject: qemu_fw_cfg: don't leak kobj on init error If platform_driver_register fails, we should cleanup fw_cfg_top_ko before exiting. Signed-off-by: Michael S. Tsirkin Acked-by: Gabriel Somlo --- drivers/firmware/qemu_fw_cfg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index fedbff55a7f3..e4c471413d46 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -727,12 +727,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) -- cgit v1.2.3 From 05dbcb430795b2e1fb1d5c757f8619d3dbed0a1c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 3 Apr 2016 15:23:37 +0300 Subject: virtio: virtio 1.0 cs04 spec compliance for reset The spec says: after writing 0 to device_status, the driver MUST wait for a read of device_status to return 0 before reinitializing the device. Cc: stable@vger.kernel.org Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/virtio/virtio_pci_modern.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index f6f28cc7eb45..e76bd91a29da 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -17,6 +17,7 @@ * */ +#include #define VIRTIO_PCI_NO_LEGACY #include "virtio_pci_common.h" @@ -271,9 +272,13 @@ static void vp_reset(struct virtio_device *vdev) struct virtio_pci_device *vp_dev = to_vp_device(vdev); /* 0 status means a reset. */ vp_iowrite8(0, &vp_dev->common->device_status); - /* Flush out the status write, and flush in device writes, - * including MSI-X interrupts, if any. */ - vp_ioread8(&vp_dev->common->device_status); + /* After writing 0 to device_status, the driver MUST wait for a read of + * device_status to return 0 before reinitializing the device. + * This will flush out the status write, and flush in device writes, + * including MSI-X interrupts, if any. + */ + while (vp_ioread8(&vp_dev->common->device_status)) + msleep(1); /* Flush pending VQ/configuration callbacks. */ vp_synchronize_vectors(vdev); } -- cgit v1.2.3 From def7ac806a9ac035abf0e7573ccc8bbfd38e163c Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Tue, 8 Mar 2016 13:30:50 -0500 Subject: firmware: qemu_fw_cfg.c: hold ACPI global lock during device access Allowing for the future possibility of implementing AML-based (i.e., firmware-triggered) access to the QEMU fw_cfg device, acquire the global ACPI lock when accessing the device on behalf of the guest-side sysfs driver, to prevent any potential race conditions. Suggested-by: Michael S. Tsirkin Signed-off-by: Gabriel Somlo Signed-off-by: Michael S. Tsirkin --- drivers/firmware/qemu_fw_cfg.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index e4c471413d46..815c4a5cae54 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 */ -- cgit v1.2.3