From e165b60b89fd840312157b91d0ea2ac0d94d98f1 Mon Sep 17 00:00:00 2001
From: Bruce Rogers <brogers@suse.com>
Date: Tue, 23 Jan 2018 15:48:03 -0700
Subject: [PATCH] S390-virtio-logicsize

---
 hw/s390-virtio-bus.c |  5 ++++-
 hw/s390-virtio-bus.h |  1 +
 hw/virtio-blk.c      | 20 ++++++++++++++++++++
 hw/virtio-pci.c      |  4 ++++
 hw/virtio.h          |  5 +++++
 5 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 61aad44ee1..eeb5c4f1f6 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -129,7 +129,8 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_blk_init((DeviceState *)dev, dev->dinfo);
+    vdev = virtio_blk_init((DeviceState *)dev, dev->dinfo,
+                           dev->logical_block_size);
     if (!vdev) {
         return -1;
     }
@@ -339,6 +340,8 @@ static VirtIOS390DeviceInfo s390_virtio_blk = {
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("drive", VirtIOS390Device, dinfo),
+        DEFINE_PROP_UINT32("logical_block_size", VirtIOS390Device,
+                           logical_block_size, 512),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index aea70902ba..f0ce43e5fb 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -44,6 +44,7 @@ typedef struct VirtIOS390Device {
     uint8_t feat_len;
     VirtIODevice *vdev;
     DriveInfo *dinfo;
+    uint32_t logical_block_size;
     NICConf nic;
 } VirtIOS390Device;
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 1681965545..a7277a96f9 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -28,6 +28,7 @@ typedef struct VirtIOBlock
     char serial_str[BLOCK_SERIAL_STRLEN + 1];
     QEMUBH *bh;
     size_t config_size;
+    uint16_t logical_block_size;
 } VirtIOBlock;
 
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -466,6 +467,9 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     blkcfg.heads = heads;
     blkcfg.sectors = secs;
     blkcfg.size_max = 0;
+#if defined(TARGET_S390X)
+    blkcfg._blk_size = s->logical_block_size;
+#endif
     virtio_identify_template(&blkcfg);
     memcpy(&blkcfg.identify[VIRTIO_BLK_ID_SN], s->serial_str,
         VIRTIO_BLK_ID_SN_BYTES);
@@ -479,6 +483,9 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 
     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
     features |= (1 << VIRTIO_BLK_F_GEOMETRY);
+#if defined(TARGET_S390X)
+    features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
+#endif
 
     if (bdrv_enable_write_cache(s->bs))
         features |= (1 << VIRTIO_BLK_F_WCACHE);
@@ -527,14 +534,23 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
+#if defined(TARGET_S390X)
+VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo,
+                              uint16_t logical_block_size)
+#else
 VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo)
+#endif
 {
     VirtIOBlock *s;
     int cylinders, heads, secs;
     static int virtio_blk_id;
     char *ps = (char *)drive_get_serial(dinfo->bdrv);
     size_t size = strlen(ps) ? sizeof(struct virtio_blk_config) :
+#if defined(TARGET_S390X)
+	    offsetof(struct virtio_blk_config, identify[0]);
+#else
 	    offsetof(struct virtio_blk_config, _blk_size);
+#endif
 
     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                           size,
@@ -546,6 +562,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo)
     s->vdev.reset = virtio_blk_reset;
     s->bs = dinfo->bdrv;
     s->rq = NULL;
+#if defined(TARGET_S390X)
+    s->logical_block_size = logical_block_size;
+    s->bs->buffer_alignment = s->logical_block_size;
+#endif
     if (strlen(ps))
         strncpy(s->serial_str, ps, sizeof(s->serial_str));
     else
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 0f79ba4827..afd2fe3388 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -462,7 +462,11 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
         qemu_error("virtio-blk-pci: drive property not set\n");
         return -1;
     }
+#if defined(TARGET_S390X)
+    vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo, 512);
+#else
     vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo);
+#endif
     vdev->nvectors = proxy->nvectors;
     virtio_init_pci(proxy, vdev,
                     PCI_VENDOR_ID_REDHAT_QUMRANET,
diff --git a/hw/virtio.h b/hw/virtio.h
index 35532a6f25..d539bab321 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -169,7 +169,12 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                         void *opaque);
 
 /* Base devices.  */
+#if defined(TARGET_S390X)
+VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo,
+                              uint16_t logical_block_size);
+#else
 VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
+#endif
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_console_init(DeviceState *dev);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
