virtio/qemu: fixes for 4.6

A couple of fixes for virtio and for the new QEMU fw cfg driver.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJXBlD5AAoJECgfDbjSjVRpgBEIALM/FXdZHX4TE1eCSxQE341e
 28/1HjeNH7IKehj2yypakopTRBPUXo7P+pyQXzsIdu3hQGA9/dqyA/1jAxfqV92/
 NN6SEqiNAWR/lIXc9a2NPDtve96v1A1E5MNzjiVuEzLUqGOVDZTzvOeqEIvE/425
 GIkkHR3bKpshHulg2UENXSVlG0sGy8fLkA8a9GswXsr45kVzACimqXgtuvTvA8lU
 2beWDjsg485mMyi9a1gv2fk66yGFZQFKqZFVxo26SXZtai1Hn1as46YTrqrhNWuk
 mpNMJ8nLBR3IGbUkJs2k9okTf4cCoNdC782ZemzRKth3Kv6KEiDvVlTwUoD7CPQ=
 =47wT
 -----END PGP SIGNATURE-----

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio/qemu fixes from Michael S Tsirkin:
 "A couple of fixes for virtio and for the new QEMU fw cfg driver"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
  virtio: add VIRTIO_CONFIG_S_NEEDS_RESET device status bit
  MAINTAINERS: add entry for QEMU
  firmware: qemu_fw_cfg.c: hold ACPI global lock during device access
  virtio: virtio 1.0 cs04 spec compliance for reset
  qemu_fw_cfg: don't leak kobj on init error
This commit is contained in:
Linus Torvalds 2016-04-07 16:20:40 -07:00
commit d3436a1d03
4 changed files with 40 additions and 4 deletions

View File

@ -9142,6 +9142,13 @@ T: git git://github.com/KrasnikovEugene/wcn36xx.git
S: Supported S: Supported
F: drivers/net/wireless/ath/wcn36xx/ F: drivers/net/wireless/ath/wcn36xx/
QEMU MACHINE EMULATOR AND VIRTUALIZER SUPPORT
M: Gabriel Somlo <somlo@cmu.edu>
M: "Michael S. Tsirkin" <mst@redhat.com>
L: qemu-devel@nongnu.org
S: Maintained
F: drivers/firmware/qemu_fw_cfg.c
RADOS BLOCK DEVICE (RBD) RADOS BLOCK DEVICE (RBD)
M: Ilya Dryomov <idryomov@gmail.com> M: Ilya Dryomov <idryomov@gmail.com>
M: Sage Weil <sage@redhat.com> M: Sage Weil <sage@redhat.com>

View File

@ -77,12 +77,28 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
static inline void fw_cfg_read_blob(u16 key, static inline void fw_cfg_read_blob(u16 key,
void *buf, loff_t pos, size_t count) 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); mutex_lock(&fw_cfg_dev_lock);
iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl); iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
while (pos-- > 0) while (pos-- > 0)
ioread8(fw_cfg_reg_data); ioread8(fw_cfg_reg_data);
ioread8_rep(fw_cfg_reg_data, buf, count); ioread8_rep(fw_cfg_reg_data, buf, count);
mutex_unlock(&fw_cfg_dev_lock); mutex_unlock(&fw_cfg_dev_lock);
acpi_release_global_lock(glk);
} }
/* clean up fw_cfg device i/o */ /* clean up fw_cfg device i/o */
@ -727,12 +743,18 @@ device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);
static int __init fw_cfg_sysfs_init(void) static int __init fw_cfg_sysfs_init(void)
{ {
int ret;
/* create /sys/firmware/qemu_fw_cfg/ top level directory */ /* create /sys/firmware/qemu_fw_cfg/ top level directory */
fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj); fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj);
if (!fw_cfg_top_ko) if (!fw_cfg_top_ko)
return -ENOMEM; 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) static void __exit fw_cfg_sysfs_exit(void)

View File

@ -17,6 +17,7 @@
* *
*/ */
#include <linux/delay.h>
#define VIRTIO_PCI_NO_LEGACY #define VIRTIO_PCI_NO_LEGACY
#include "virtio_pci_common.h" #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); struct virtio_pci_device *vp_dev = to_vp_device(vdev);
/* 0 status means a reset. */ /* 0 status means a reset. */
vp_iowrite8(0, &vp_dev->common->device_status); vp_iowrite8(0, &vp_dev->common->device_status);
/* Flush out the status write, and flush in device writes, /* After writing 0 to device_status, the driver MUST wait for a read of
* including MSI-X interrupts, if any. */ * device_status to return 0 before reinitializing the device.
vp_ioread8(&vp_dev->common->device_status); * 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. */ /* Flush pending VQ/configuration callbacks. */
vp_synchronize_vectors(vdev); vp_synchronize_vectors(vdev);
} }

View File

@ -40,6 +40,8 @@
#define VIRTIO_CONFIG_S_DRIVER_OK 4 #define VIRTIO_CONFIG_S_DRIVER_OK 4
/* Driver has finished configuring features */ /* Driver has finished configuring features */
#define VIRTIO_CONFIG_S_FEATURES_OK 8 #define VIRTIO_CONFIG_S_FEATURES_OK 8
/* Device entered invalid state, driver must reset it */
#define VIRTIO_CONFIG_S_NEEDS_RESET 0x40
/* We've given up on this device. */ /* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80 #define VIRTIO_CONFIG_S_FAILED 0x80