Blame SOURCES/kvm-hw-scsi-cleanups-before-VPD-BL-emulation.patch

7711c0
From 3597e0269b24fe17de30e1554f33b1770852211b Mon Sep 17 00:00:00 2001
7711c0
From: Paolo Bonzini <pbonzini@redhat.com>
7711c0
Date: Wed, 7 Nov 2018 18:00:00 +0100
7711c0
Subject: [PATCH 26/34] hw/scsi: cleanups before VPD BL emulation
7711c0
MIME-Version: 1.0
7711c0
Content-Type: text/plain; charset=UTF-8
7711c0
Content-Transfer-Encoding: 8bit
7711c0
7711c0
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
7711c0
Message-id: <20181107180007.22954-3-pbonzini@redhat.com>
7711c0
Patchwork-id: 82948
7711c0
O-Subject: [RHEL7.6.z qemu-kvm-rhev PATCH 2/9] hw/scsi: cleanups before VPD BL emulation
7711c0
Bugzilla: 1566195
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7711c0
7711c0
From: Daniel Henrique Barboza <danielhb413@gmail.com>
7711c0
7711c0
To add support for the emulation of Block Limits VPD page
7711c0
for passthrough devices, a few adjustments in the current code
7711c0
base is required to avoid repetition and improve clarity.
7711c0
7711c0
In scsi-generic.c, detach the Inquiry handling from
7711c0
scsi_read_complete and put it into a new function called
7711c0
scsi_handle_inquiry_reply. This change aims to avoid
7711c0
cluttering of scsi_read_complete when we more logic in the
7711c0
Inquiry response handling is added in the next patches,
7711c0
centralizing the changes in the new function.
7711c0
7711c0
In scsi-disk.c, take the build of all emulated VPD pages
7711c0
from scsi_disk_emulate_inquiry and make it available to
7711c0
other files into a non-static function called
7711c0
scsi_disk_emulate_vpd_page. Making it public will allow
7711c0
the future VPD BL emulation code for passthrough devices
7711c0
to use it from scsi-generic.c, avoiding copy/pasting this
7711c0
code solely for that purpose. It also has the advantage of
7711c0
providing emulation of all VPD pages in case we need to
7711c0
emulate other pages in other scenarios. As a bonus,
7711c0
scsi_disk_emulate_inquiry got tidier.
7711c0
7711c0
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
7711c0
Message-Id: <20180627172432.11120-2-danielhb413@gmail.com>
7711c0
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7711c0
(cherry picked from commit 0a96ca2437646bad197b0108c5f4a93e7ead05a9)
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 hw/scsi/scsi-disk.c    | 407 +++++++++++++++++++++++++------------------------
7711c0
 hw/scsi/scsi-generic.c |  71 +++++----
7711c0
 include/hw/scsi/scsi.h |   1 +
7711c0
 3 files changed, 249 insertions(+), 230 deletions(-)
7711c0
7711c0
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
7711c0
index ded23d3..ae5b4c0 100644
7711c0
--- a/hw/scsi/scsi-disk.c
7711c0
+++ b/hw/scsi/scsi-disk.c
7711c0
@@ -585,219 +585,228 @@ static uint8_t *scsi_get_buf(SCSIRequest *req)
7711c0
     return (uint8_t *)r->iov.iov_base;
7711c0
 }
7711c0
 
7711c0
-static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
7711c0
+int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
7711c0
 {
7711c0
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
7711c0
-    int buflen = 0;
7711c0
-    int start;
7711c0
-
7711c0
-    if (req->cmd.buf[1] & 0x1) {
7711c0
-        /* Vital product data */
7711c0
-        uint8_t page_code = req->cmd.buf[2];
7711c0
-
7711c0
-        outbuf[buflen++] = s->qdev.type & 0x1f;
7711c0
-        outbuf[buflen++] = page_code ; // this page
7711c0
-        outbuf[buflen++] = 0x00;
7711c0
-        outbuf[buflen++] = 0x00;
7711c0
-        start = buflen;
7711c0
-
7711c0
-        switch (page_code) {
7711c0
-        case 0x00: /* Supported page codes, mandatory */
7711c0
-        {
7711c0
-            DPRINTF("Inquiry EVPD[Supported pages] "
7711c0
-                    "buffer size %zd\n", req->cmd.xfer);
7711c0
-            outbuf[buflen++] = 0x00; // list of supported pages (this page)
7711c0
-            if (s->serial) {
7711c0
-                outbuf[buflen++] = 0x80; // unit serial number
7711c0
-            }
7711c0
-            outbuf[buflen++] = 0x83; // device identification
7711c0
-            if (s->qdev.type == TYPE_DISK) {
7711c0
-                outbuf[buflen++] = 0xb0; // block limits
7711c0
-                outbuf[buflen++] = 0xb1; /* block device characteristics */
7711c0
-                outbuf[buflen++] = 0xb2; // thin provisioning
7711c0
-            }
7711c0
-            break;
7711c0
-        }
7711c0
-        case 0x80: /* Device serial number, optional */
7711c0
-        {
7711c0
-            int l;
7711c0
+    uint8_t page_code = req->cmd.buf[2];
7711c0
+    int start, buflen = 0;
7711c0
 
7711c0
-            if (!s->serial) {
7711c0
-                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
7711c0
-                return -1;
7711c0
-            }
7711c0
+    outbuf[buflen++] = s->qdev.type & 0x1f;
7711c0
+    outbuf[buflen++] = page_code;
7711c0
+    outbuf[buflen++] = 0x00;
7711c0
+    outbuf[buflen++] = 0x00;
7711c0
+    start = buflen;
7711c0
 
7711c0
-            l = strlen(s->serial);
7711c0
-            if (l > 36) {
7711c0
-                l = 36;
7711c0
-            }
7711c0
+    switch (page_code) {
7711c0
+    case 0x00: /* Supported page codes, mandatory */
7711c0
+    {
7711c0
+        DPRINTF("Inquiry EVPD[Supported pages] "
7711c0
+                "buffer size %zd\n", req->cmd.xfer);
7711c0
+        outbuf[buflen++] = 0x00; /* list of supported pages (this page) */
7711c0
+        if (s->serial) {
7711c0
+            outbuf[buflen++] = 0x80; /* unit serial number */
7711c0
+        }
7711c0
+        outbuf[buflen++] = 0x83; /* device identification */
7711c0
+        if (s->qdev.type == TYPE_DISK) {
7711c0
+            outbuf[buflen++] = 0xb0; /* block limits */
7711c0
+            outbuf[buflen++] = 0xb1; /* block device characteristics */
7711c0
+            outbuf[buflen++] = 0xb2; /* thin provisioning */
7711c0
+        }
7711c0
+        break;
7711c0
+    }
7711c0
+    case 0x80: /* Device serial number, optional */
7711c0
+    {
7711c0
+        int l;
7711c0
 
7711c0
-            DPRINTF("Inquiry EVPD[Serial number] "
7711c0
-                    "buffer size %zd\n", req->cmd.xfer);
7711c0
-            memcpy(outbuf+buflen, s->serial, l);
7711c0
-            buflen += l;
7711c0
-            break;
7711c0
+        if (!s->serial) {
7711c0
+            DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
7711c0
+            return -1;
7711c0
         }
7711c0
 
7711c0
-        case 0x83: /* Device identification page, mandatory */
7711c0
-        {
7711c0
-            const char *str = s->serial ?: blk_name(s->qdev.conf.blk);
7711c0
-            int max_len = s->serial ? 20 : 255 - 8;
7711c0
-            int id_len = strlen(str);
7711c0
+        l = strlen(s->serial);
7711c0
+        if (l > 36) {
7711c0
+            l = 36;
7711c0
+        }
7711c0
 
7711c0
-            if (id_len > max_len) {
7711c0
-                id_len = max_len;
7711c0
-            }
7711c0
-            DPRINTF("Inquiry EVPD[Device identification] "
7711c0
-                    "buffer size %zd\n", req->cmd.xfer);
7711c0
-
7711c0
-            outbuf[buflen++] = 0x2; // ASCII
7711c0
-            outbuf[buflen++] = 0;   // not officially assigned
7711c0
-            outbuf[buflen++] = 0;   // reserved
7711c0
-            outbuf[buflen++] = id_len; // length of data following
7711c0
-            memcpy(outbuf+buflen, str, id_len);
7711c0
-            buflen += id_len;
7711c0
-
7711c0
-            if (s->qdev.wwn) {
7711c0
-                outbuf[buflen++] = 0x1; // Binary
7711c0
-                outbuf[buflen++] = 0x3; // NAA
7711c0
-                outbuf[buflen++] = 0;   // reserved
7711c0
-                outbuf[buflen++] = 8;
7711c0
-                stq_be_p(&outbuf[buflen], s->qdev.wwn);
7711c0
-                buflen += 8;
7711c0
-            }
7711c0
+        DPRINTF("Inquiry EVPD[Serial number] "
7711c0
+                "buffer size %zd\n", req->cmd.xfer);
7711c0
+        memcpy(outbuf + buflen, s->serial, l);
7711c0
+        buflen += l;
7711c0
+        break;
7711c0
+    }
7711c0
 
7711c0
-            if (s->qdev.port_wwn) {
7711c0
-                outbuf[buflen++] = 0x61; // SAS / Binary
7711c0
-                outbuf[buflen++] = 0x93; // PIV / Target port / NAA
7711c0
-                outbuf[buflen++] = 0;    // reserved
7711c0
-                outbuf[buflen++] = 8;
7711c0
-                stq_be_p(&outbuf[buflen], s->qdev.port_wwn);
7711c0
-                buflen += 8;
7711c0
-            }
7711c0
+    case 0x83: /* Device identification page, mandatory */
7711c0
+    {
7711c0
+        const char *str = s->serial ?: blk_name(s->qdev.conf.blk);
7711c0
+        int max_len = s->serial ? 20 : 255 - 8;
7711c0
+        int id_len = strlen(str);
7711c0
 
7711c0
-            if (s->port_index) {
7711c0
-                outbuf[buflen++] = 0x61; // SAS / Binary
7711c0
-                outbuf[buflen++] = 0x94; // PIV / Target port / relative target port
7711c0
-                outbuf[buflen++] = 0;    // reserved
7711c0
-                outbuf[buflen++] = 4;
7711c0
-                stw_be_p(&outbuf[buflen + 2], s->port_index);
7711c0
-                buflen += 4;
7711c0
-            }
7711c0
-            break;
7711c0
+        if (id_len > max_len) {
7711c0
+            id_len = max_len;
7711c0
         }
7711c0
-        case 0xb0: /* block limits */
7711c0
-        {
7711c0
-            unsigned int unmap_sectors =
7711c0
-                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
7711c0
-            unsigned int min_io_size =
7711c0
-                    s->qdev.conf.min_io_size / s->qdev.blocksize;
7711c0
-            unsigned int opt_io_size =
7711c0
-                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
7711c0
-            unsigned int max_unmap_sectors =
7711c0
-                    s->max_unmap_size / s->qdev.blocksize;
7711c0
-            unsigned int max_io_sectors =
7711c0
-                    s->max_io_size / s->qdev.blocksize;
7711c0
-
7711c0
-            if (s->qdev.type == TYPE_ROM) {
7711c0
-                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
7711c0
-                        page_code);
7711c0
-                return -1;
7711c0
-            }
7711c0
-            if (s->qdev.type == TYPE_DISK) {
7711c0
-                int max_transfer_blk = blk_get_max_transfer(s->qdev.conf.blk);
7711c0
-                int max_io_sectors_blk =
7711c0
-                    max_transfer_blk / s->qdev.blocksize;
7711c0
-
7711c0
-                max_io_sectors =
7711c0
-                    MIN_NON_ZERO(max_io_sectors_blk, max_io_sectors);
7711c0
-
7711c0
-                /* min_io_size and opt_io_size can't be greater than
7711c0
-                 * max_io_sectors */
7711c0
-                if (min_io_size) {
7711c0
-                    min_io_size = MIN(min_io_size, max_io_sectors);
7711c0
-                }
7711c0
-                if (opt_io_size) {
7711c0
-                    opt_io_size = MIN(opt_io_size, max_io_sectors);
7711c0
-                }
7711c0
-            }
7711c0
-            /* required VPD size with unmap support */
7711c0
-            buflen = 0x40;
7711c0
-            memset(outbuf + 4, 0, buflen - 4);
7711c0
-
7711c0
-            outbuf[4] = 0x1; /* wsnz */
7711c0
-
7711c0
-            /* optimal transfer length granularity */
7711c0
-            outbuf[6] = (min_io_size >> 8) & 0xff;
7711c0
-            outbuf[7] = min_io_size & 0xff;
7711c0
-
7711c0
-            /* maximum transfer length */
7711c0
-            outbuf[8] = (max_io_sectors >> 24) & 0xff;
7711c0
-            outbuf[9] = (max_io_sectors >> 16) & 0xff;
7711c0
-            outbuf[10] = (max_io_sectors >> 8) & 0xff;
7711c0
-            outbuf[11] = max_io_sectors & 0xff;
7711c0
-
7711c0
-            /* optimal transfer length */
7711c0
-            outbuf[12] = (opt_io_size >> 24) & 0xff;
7711c0
-            outbuf[13] = (opt_io_size >> 16) & 0xff;
7711c0
-            outbuf[14] = (opt_io_size >> 8) & 0xff;
7711c0
-            outbuf[15] = opt_io_size & 0xff;
7711c0
-
7711c0
-            /* max unmap LBA count, default is 1GB */
7711c0
-            outbuf[20] = (max_unmap_sectors >> 24) & 0xff;
7711c0
-            outbuf[21] = (max_unmap_sectors >> 16) & 0xff;
7711c0
-            outbuf[22] = (max_unmap_sectors >> 8) & 0xff;
7711c0
-            outbuf[23] = max_unmap_sectors & 0xff;
7711c0
-
7711c0
-            /* max unmap descriptors, 255 fit in 4 kb with an 8-byte header.  */
7711c0
-            outbuf[24] = 0;
7711c0
-            outbuf[25] = 0;
7711c0
-            outbuf[26] = 0;
7711c0
-            outbuf[27] = 255;
7711c0
-
7711c0
-            /* optimal unmap granularity */
7711c0
-            outbuf[28] = (unmap_sectors >> 24) & 0xff;
7711c0
-            outbuf[29] = (unmap_sectors >> 16) & 0xff;
7711c0
-            outbuf[30] = (unmap_sectors >> 8) & 0xff;
7711c0
-            outbuf[31] = unmap_sectors & 0xff;
7711c0
-
7711c0
-            /* max write same size */
7711c0
-            outbuf[36] = 0;
7711c0
-            outbuf[37] = 0;
7711c0
-            outbuf[38] = 0;
7711c0
-            outbuf[39] = 0;
7711c0
-
7711c0
-            outbuf[40] = (max_io_sectors >> 24) & 0xff;
7711c0
-            outbuf[41] = (max_io_sectors >> 16) & 0xff;
7711c0
-            outbuf[42] = (max_io_sectors >> 8) & 0xff;
7711c0
-            outbuf[43] = max_io_sectors & 0xff;
7711c0
-            break;
7711c0
+        DPRINTF("Inquiry EVPD[Device identification] "
7711c0
+                "buffer size %zd\n", req->cmd.xfer);
7711c0
+
7711c0
+        outbuf[buflen++] = 0x2; /* ASCII */
7711c0
+        outbuf[buflen++] = 0;   /* not officially assigned */
7711c0
+        outbuf[buflen++] = 0;   /* reserved */
7711c0
+        outbuf[buflen++] = id_len; /* length of data following */
7711c0
+        memcpy(outbuf + buflen, str, id_len);
7711c0
+        buflen += id_len;
7711c0
+
7711c0
+        if (s->qdev.wwn) {
7711c0
+            outbuf[buflen++] = 0x1; /* Binary */
7711c0
+            outbuf[buflen++] = 0x3; /* NAA */
7711c0
+            outbuf[buflen++] = 0;   /* reserved */
7711c0
+            outbuf[buflen++] = 8;
7711c0
+            stq_be_p(&outbuf[buflen], s->qdev.wwn);
7711c0
+            buflen += 8;
7711c0
         }
7711c0
-        case 0xb1: /* block device characteristics */
7711c0
-        {
7711c0
-            buflen = 8;
7711c0
-            outbuf[4] = (s->rotation_rate >> 8) & 0xff;
7711c0
-            outbuf[5] = s->rotation_rate & 0xff;
7711c0
-            outbuf[6] = 0;
7711c0
-            outbuf[7] = 0;
7711c0
-            break;
7711c0
+
7711c0
+        if (s->qdev.port_wwn) {
7711c0
+            outbuf[buflen++] = 0x61; /* SAS / Binary */
7711c0
+            outbuf[buflen++] = 0x93; /* PIV / Target port / NAA */
7711c0
+            outbuf[buflen++] = 0;    /* reserved */
7711c0
+            outbuf[buflen++] = 8;
7711c0
+            stq_be_p(&outbuf[buflen], s->qdev.port_wwn);
7711c0
+            buflen += 8;
7711c0
         }
7711c0
-        case 0xb2: /* thin provisioning */
7711c0
-        {
7711c0
-            buflen = 8;
7711c0
-            outbuf[4] = 0;
7711c0
-            outbuf[5] = 0xe0; /* unmap & write_same 10/16 all supported */
7711c0
-            outbuf[6] = s->qdev.conf.discard_granularity ? 2 : 1;
7711c0
-            outbuf[7] = 0;
7711c0
-            break;
7711c0
+
7711c0
+        if (s->port_index) {
7711c0
+            outbuf[buflen++] = 0x61; /* SAS / Binary */
7711c0
+
7711c0
+            /* PIV/Target port/relative target port */
7711c0
+            outbuf[buflen++] = 0x94;
7711c0
+
7711c0
+            outbuf[buflen++] = 0;    /* reserved */
7711c0
+            outbuf[buflen++] = 4;
7711c0
+            stw_be_p(&outbuf[buflen + 2], s->port_index);
7711c0
+            buflen += 4;
7711c0
         }
7711c0
-        default:
7711c0
+        break;
7711c0
+    }
7711c0
+    case 0xb0: /* block limits */
7711c0
+    {
7711c0
+        unsigned int unmap_sectors =
7711c0
+            s->qdev.conf.discard_granularity / s->qdev.blocksize;
7711c0
+        unsigned int min_io_size =
7711c0
+            s->qdev.conf.min_io_size / s->qdev.blocksize;
7711c0
+        unsigned int opt_io_size =
7711c0
+            s->qdev.conf.opt_io_size / s->qdev.blocksize;
7711c0
+        unsigned int max_unmap_sectors =
7711c0
+            s->max_unmap_size / s->qdev.blocksize;
7711c0
+        unsigned int max_io_sectors =
7711c0
+            s->max_io_size / s->qdev.blocksize;
7711c0
+
7711c0
+        if (s->qdev.type == TYPE_ROM) {
7711c0
+            DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
7711c0
+                    page_code);
7711c0
             return -1;
7711c0
         }
7711c0
-        /* done with EVPD */
7711c0
-        assert(buflen - start <= 255);
7711c0
-        outbuf[start - 1] = buflen - start;
7711c0
-        return buflen;
7711c0
+        if (s->qdev.type == TYPE_DISK) {
7711c0
+            int max_transfer_blk = blk_get_max_transfer(s->qdev.conf.blk);
7711c0
+            int max_io_sectors_blk =
7711c0
+                max_transfer_blk / s->qdev.blocksize;
7711c0
+
7711c0
+            max_io_sectors =
7711c0
+                MIN_NON_ZERO(max_io_sectors_blk, max_io_sectors);
7711c0
+
7711c0
+            /* min_io_size and opt_io_size can't be greater than
7711c0
+             * max_io_sectors */
7711c0
+            if (min_io_size) {
7711c0
+                min_io_size = MIN(min_io_size, max_io_sectors);
7711c0
+            }
7711c0
+            if (opt_io_size) {
7711c0
+                opt_io_size = MIN(opt_io_size, max_io_sectors);
7711c0
+            }
7711c0
+        }
7711c0
+        /* required VPD size with unmap support */
7711c0
+        buflen = 0x40;
7711c0
+        memset(outbuf + 4, 0, buflen - 4);
7711c0
+
7711c0
+        outbuf[4] = 0x1; /* wsnz */
7711c0
+
7711c0
+        /* optimal transfer length granularity */
7711c0
+        outbuf[6] = (min_io_size >> 8) & 0xff;
7711c0
+        outbuf[7] = min_io_size & 0xff;
7711c0
+
7711c0
+        /* maximum transfer length */
7711c0
+        outbuf[8] = (max_io_sectors >> 24) & 0xff;
7711c0
+        outbuf[9] = (max_io_sectors >> 16) & 0xff;
7711c0
+        outbuf[10] = (max_io_sectors >> 8) & 0xff;
7711c0
+        outbuf[11] = max_io_sectors & 0xff;
7711c0
+
7711c0
+        /* optimal transfer length */
7711c0
+        outbuf[12] = (opt_io_size >> 24) & 0xff;
7711c0
+        outbuf[13] = (opt_io_size >> 16) & 0xff;
7711c0
+        outbuf[14] = (opt_io_size >> 8) & 0xff;
7711c0
+        outbuf[15] = opt_io_size & 0xff;
7711c0
+
7711c0
+        /* max unmap LBA count, default is 1GB */
7711c0
+        outbuf[20] = (max_unmap_sectors >> 24) & 0xff;
7711c0
+        outbuf[21] = (max_unmap_sectors >> 16) & 0xff;
7711c0
+        outbuf[22] = (max_unmap_sectors >> 8) & 0xff;
7711c0
+        outbuf[23] = max_unmap_sectors & 0xff;
7711c0
+
7711c0
+        /* max unmap descriptors, 255 fit in 4 kb with an 8-byte header */
7711c0
+        outbuf[24] = 0;
7711c0
+        outbuf[25] = 0;
7711c0
+        outbuf[26] = 0;
7711c0
+        outbuf[27] = 255;
7711c0
+
7711c0
+        /* optimal unmap granularity */
7711c0
+        outbuf[28] = (unmap_sectors >> 24) & 0xff;
7711c0
+        outbuf[29] = (unmap_sectors >> 16) & 0xff;
7711c0
+        outbuf[30] = (unmap_sectors >> 8) & 0xff;
7711c0
+        outbuf[31] = unmap_sectors & 0xff;
7711c0
+
7711c0
+        /* max write same size */
7711c0
+        outbuf[36] = 0;
7711c0
+        outbuf[37] = 0;
7711c0
+        outbuf[38] = 0;
7711c0
+        outbuf[39] = 0;
7711c0
+
7711c0
+        outbuf[40] = (max_io_sectors >> 24) & 0xff;
7711c0
+        outbuf[41] = (max_io_sectors >> 16) & 0xff;
7711c0
+        outbuf[42] = (max_io_sectors >> 8) & 0xff;
7711c0
+        outbuf[43] = max_io_sectors & 0xff;
7711c0
+        break;
7711c0
+    }
7711c0
+    case 0xb1: /* block device characteristics */
7711c0
+    {
7711c0
+        buflen = 8;
7711c0
+        outbuf[4] = (s->rotation_rate >> 8) & 0xff;
7711c0
+        outbuf[5] = s->rotation_rate & 0xff;
7711c0
+        outbuf[6] = 0;
7711c0
+        outbuf[7] = 0;
7711c0
+        break;
7711c0
+    }
7711c0
+    case 0xb2: /* thin provisioning */
7711c0
+    {
7711c0
+        buflen = 8;
7711c0
+        outbuf[4] = 0;
7711c0
+        outbuf[5] = 0xe0; /* unmap & write_same 10/16 all supported */
7711c0
+        outbuf[6] = s->qdev.conf.discard_granularity ? 2 : 1;
7711c0
+        outbuf[7] = 0;
7711c0
+        break;
7711c0
+    }
7711c0
+    default:
7711c0
+        return -1;
7711c0
+    }
7711c0
+    /* done with EVPD */
7711c0
+    assert(buflen - start <= 255);
7711c0
+    outbuf[start - 1] = buflen - start;
7711c0
+    return buflen;
7711c0
+}
7711c0
+
7711c0
+static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
7711c0
+{
7711c0
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
7711c0
+    int buflen = 0;
7711c0
+
7711c0
+    if (req->cmd.buf[1] & 0x1) {
7711c0
+        /* Vital product data */
7711c0
+        return scsi_disk_emulate_vpd_page(req, outbuf);
7711c0
     }
7711c0
 
7711c0
     /* Standard INQUIRY data */
7711c0
@@ -3040,6 +3049,10 @@ static Property scsi_block_properties[] = {
7711c0
     DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
7711c0
     DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false),
7711c0
     DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0),
7711c0
+    DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size,
7711c0
+                       DEFAULT_MAX_UNMAP_SIZE),
7711c0
+    DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size,
7711c0
+                       DEFAULT_MAX_IO_SIZE),
7711c0
     DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
7711c0
                       -1),
7711c0
     DEFINE_PROP_END_OF_LIST(),
7711c0
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
7711c0
index 381f04e..796162c 100644
7711c0
--- a/hw/scsi/scsi-generic.c
7711c0
+++ b/hw/scsi/scsi-generic.c
7711c0
@@ -143,6 +143,43 @@ static int execute_command(BlockBackend *blk,
7711c0
     return 0;
7711c0
 }
7711c0
 
7711c0
+static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
7711c0
+{
7711c0
+    /*
7711c0
+     *  EVPD set to zero returns the standard INQUIRY data.
7711c0
+     *
7711c0
+     *  Check if scsi_version is unset (-1) to avoid re-defining it
7711c0
+     *  each time an INQUIRY with standard data is received.
7711c0
+     *  scsi_version is initialized with -1 in scsi_generic_reset
7711c0
+     *  and scsi_disk_reset, making sure that we'll set the
7711c0
+     *  scsi_version after a reset. If the version field of the
7711c0
+     *  INQUIRY response somehow changes after a guest reboot,
7711c0
+     *  we'll be able to keep track of it.
7711c0
+     *
7711c0
+     *  On SCSI-2 and older, first 3 bits of byte 2 is the
7711c0
+     *  ANSI-approved version, while on later versions the
7711c0
+     *  whole byte 2 contains the version. Check if we're dealing
7711c0
+     *  with a newer version and, in that case, assign the
7711c0
+     *  whole byte.
7711c0
+     */
7711c0
+    if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
7711c0
+        s->scsi_version = r->buf[2] & 0x07;
7711c0
+        if (s->scsi_version > 2) {
7711c0
+            s->scsi_version = r->buf[2];
7711c0
+        }
7711c0
+    }
7711c0
+    if (s->type == TYPE_DISK && r->req.cmd.buf[2] == 0xb0) {
7711c0
+        uint32_t max_transfer =
7711c0
+            blk_get_max_transfer(s->conf.blk) / s->blocksize;
7711c0
+
7711c0
+        assert(max_transfer);
7711c0
+        stl_be_p(&r->buf[8], max_transfer);
7711c0
+        /* Also take care of the opt xfer len. */
7711c0
+        stl_be_p(&r->buf[12],
7711c0
+                 MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
7711c0
+    }
7711c0
+}
7711c0
+
7711c0
 static void scsi_read_complete(void * opaque, int ret)
7711c0
 {
7711c0
     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
7711c0
@@ -195,39 +232,7 @@ static void scsi_read_complete(void * opaque, int ret)
7711c0
         }
7711c0
     }
7711c0
     if (r->req.cmd.buf[0] == INQUIRY) {
7711c0
-        /*
7711c0
-         *  EVPD set to zero returns the standard INQUIRY data.
7711c0
-         *
7711c0
-         *  Check if scsi_version is unset (-1) to avoid re-defining it
7711c0
-         *  each time an INQUIRY with standard data is received.
7711c0
-         *  scsi_version is initialized with -1 in scsi_generic_reset
7711c0
-         *  and scsi_disk_reset, making sure that we'll set the
7711c0
-         *  scsi_version after a reset. If the version field of the
7711c0
-         *  INQUIRY response somehow changes after a guest reboot,
7711c0
-         *  we'll be able to keep track of it.
7711c0
-         *
7711c0
-         *  On SCSI-2 and older, first 3 bits of byte 2 is the
7711c0
-         *  ANSI-approved version, while on later versions the
7711c0
-         *  whole byte 2 contains the version. Check if we're dealing
7711c0
-         *  with a newer version and, in that case, assign the
7711c0
-         *  whole byte.
7711c0
-         */
7711c0
-        if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
7711c0
-            s->scsi_version = r->buf[2] & 0x07;
7711c0
-            if (s->scsi_version > 2) {
7711c0
-                s->scsi_version = r->buf[2];
7711c0
-            }
7711c0
-        }
7711c0
-        if (s->type == TYPE_DISK && r->req.cmd.buf[2] == 0xb0) {
7711c0
-            uint32_t max_transfer =
7711c0
-                blk_get_max_transfer(s->conf.blk) / s->blocksize;
7711c0
-
7711c0
-            assert(max_transfer);
7711c0
-            stl_be_p(&r->buf[8], max_transfer);
7711c0
-            /* Also take care of the opt xfer len. */
7711c0
-            stl_be_p(&r->buf[12],
7711c0
-                     MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
7711c0
-        }
7711c0
+        scsi_handle_inquiry_reply(r, s);
7711c0
     }
7711c0
     scsi_req_data(&r->req, len);
7711c0
     scsi_req_unref(&r->req);
7711c0
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
7711c0
index 1a7290d..5930a43 100644
7711c0
--- a/include/hw/scsi/scsi.h
7711c0
+++ b/include/hw/scsi/scsi.h
7711c0
@@ -188,6 +188,7 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
7711c0
 void scsi_device_unit_attention_reported(SCSIDevice *dev);
7711c0
 void scsi_generic_read_device_identification(SCSIDevice *dev);
7711c0
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
7711c0
+int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf);
7711c0
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
7711c0
 
7711c0
 /* scsi-generic.c. */
7711c0
-- 
7711c0
1.8.3.1
7711c0