]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/scsi/spapr_vscsi.c
Do not include cpu.h if it's not really necessary
[mirror_qemu.git] / hw / scsi / spapr_vscsi.c
index b00edf7fd48a8fe9b95e986314590caf46d1f78e..c210262484afa28d77355e76439b9e7d53be4a0b 100644 (file)
  *  - Add indirect descriptors support
  *  - Maybe do autosense (PAPR seems to mandate it, linux doesn't care)
  */
+
 #include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "hw/hw.h"
+#include "qemu/module.h"
 #include "hw/scsi/scsi.h"
-#include "block/scsi.h"
+#include "migration/vmstate.h"
+#include "scsi/constants.h"
 #include "srp.h"
-#include "hw/qdev.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
+#include "hw/qdev-properties.h"
 #include "viosrp.h"
+#include "trace.h"
 
 #include <libfdt.h>
-
-/*#define DEBUG_VSCSI*/
-
-#ifdef DEBUG_VSCSI
-#define DPRINTF(fmt, ...) \
-    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
+#include "qom/object.h"
 
 /*
  * Virtual SCSI device
@@ -63,6 +55,8 @@
 #define VSCSI_MAX_SECTORS       4096
 #define VSCSI_REQ_LIMIT         24
 
+/* Maximum size of a IU payload */
+#define SRP_MAX_IU_DATA_LEN     (SRP_MAX_IU_LEN - sizeof(union srp_iu))
 #define SRP_RSP_SENSE_DATA_LEN  18
 
 #define SRP_REPORT_LUNS_WLUN    0xc10100000000000ULL
@@ -74,7 +68,7 @@ typedef union vscsi_crq {
 
 typedef struct vscsi_req {
     vscsi_crq               crq;
-    union viosrp_iu         iu;
+    uint8_t                 viosrp_iu_buf[SRP_MAX_IU_LEN];
 
     /* SCSI request tracking */
     SCSIRequest             *sreq;
@@ -96,14 +90,18 @@ typedef struct vscsi_req {
 } vscsi_req;
 
 #define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi"
-#define VIO_SPAPR_VSCSI_DEVICE(obj) \
-     OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(VSCSIState, VIO_SPAPR_VSCSI_DEVICE)
 
-typedef struct {
-    VIOsPAPRDevice vdev;
+struct VSCSIState {
+    SpaprVioDevice vdev;
     SCSIBus bus;
     vscsi_req reqs[VSCSI_REQ_LIMIT];
-} VSCSIState;
+};
+
+static union viosrp_iu *req_iu(vscsi_req *req)
+{
+    return (union viosrp_iu *)req->viosrp_iu_buf;
+}
 
 static struct vscsi_req *vscsi_get_req(VSCSIState *s)
 {
@@ -129,7 +127,7 @@ static struct vscsi_req *vscsi_find_req(VSCSIState *s, uint64_t srp_tag)
 
     for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
         req = &s->reqs[i];
-        if (req->iu.srp.cmd.tag == srp_tag) {
+        if (req_iu(req)->srp.cmd.tag == srp_tag) {
             return req;
         }
     }
@@ -184,9 +182,11 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
 {
     long rc, rc1;
 
+    assert(length <= SRP_MAX_IU_LEN);
+
     /* First copy the SRP */
     rc = spapr_vio_dma_write(&s->vdev, req->crq.s.IU_data_ptr,
-                             &req->iu, length);
+                             &req->viosrp_iu_buf, length);
     if (rc) {
         fprintf(stderr, "vscsi_send_iu: DMA write failure !\n");
     }
@@ -196,7 +196,7 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
     req->crq.s.reserved = 0x00;
     req->crq.s.timeout = cpu_to_be16(0x0000);
     req->crq.s.IU_length = cpu_to_be16(length);
-    req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
+    req->crq.s.IU_data_ptr = req_iu(req)->srp.rsp.tag; /* right byte order */
 
     if (rc == 0) {
         req->crq.s.status = VIOSRP_OK;
@@ -232,13 +232,12 @@ static void vscsi_makeup_sense(VSCSIState *s, vscsi_req *req,
 static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
                           uint8_t status, int32_t res_in, int32_t res_out)
 {
-    union viosrp_iu *iu = &req->iu;
+    union viosrp_iu *iu = req_iu(req);
     uint64_t tag = iu->srp.rsp.tag;
     int total_len = sizeof(iu->srp.rsp);
     uint8_t sol_not = iu->srp.cmd.sol_not;
 
-    DPRINTF("VSCSI: Sending resp status: 0x%x, "
-            "res_in: %d, res_out: %d\n", status, res_in, res_out);
+    trace_spapr_vscsi_send_rsp(status, res_in, res_out);
 
     memset(iu, 0, sizeof(struct srp_rsp));
     iu->srp.rsp.opcode = SRP_RSP;
@@ -270,10 +269,12 @@ static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
     if (status) {
         iu->srp.rsp.sol_not = (sol_not & 0x04) >> 2;
         if (req->senselen) {
-            req->iu.srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
-            req->iu.srp.rsp.sense_data_len = cpu_to_be32(req->senselen);
-            memcpy(req->iu.srp.rsp.data, req->sense, req->senselen);
-            total_len += req->senselen;
+            int sense_data_len = MIN(req->senselen, SRP_MAX_IU_DATA_LEN);
+
+            iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
+            iu->srp.rsp.sense_data_len = cpu_to_be32(sense_data_len);
+            memcpy(iu->srp.rsp.data, req->sense, sense_data_len);
+            total_len += sense_data_len;
         }
     } else {
         iu->srp.rsp.sol_not = (sol_not & 0x02) >> 1;
@@ -294,17 +295,17 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
                             unsigned n, unsigned buf_offset,
                             struct srp_direct_buf *ret)
 {
-    struct srp_cmd *cmd = &req->iu.srp.cmd;
+    struct srp_cmd *cmd = &req_iu(req)->srp.cmd;
 
     switch (req->dma_fmt) {
     case SRP_NO_DATA_DESC: {
-        DPRINTF("VSCSI: no data descriptor\n");
+        trace_spapr_vscsi_fetch_desc_no_data();
         return 0;
     }
     case SRP_DATA_DESC_DIRECT: {
         memcpy(ret, cmd->add_data + req->cdb_offset, sizeof(*ret));
         assert(req->cur_desc_num == 0);
-        DPRINTF("VSCSI: direct segment\n");
+        trace_spapr_vscsi_fetch_desc_direct();
         break;
     }
     case SRP_DATA_DESC_INDIRECT: {
@@ -312,30 +313,29 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
                                        (cmd->add_data + req->cdb_offset);
         if (n < req->local_desc) {
             *ret = tmp->desc_list[n];
-            DPRINTF("VSCSI: indirect segment local tag=0x%x desc#%d/%d\n",
-                    req->qtag, n, req->local_desc);
-
+            trace_spapr_vscsi_fetch_desc_indirect(req->qtag, n,
+                                                  req->local_desc);
         } else if (n < req->total_desc) {
             int rc;
             struct srp_direct_buf tbl_desc = vscsi_swap_desc(tmp->table_desc);
             unsigned desc_offset = n * sizeof(struct srp_direct_buf);
 
             if (desc_offset >= tbl_desc.len) {
-                DPRINTF("VSCSI:   #%d is ouf of range (%d bytes)\n",
-                        n, desc_offset);
+                trace_spapr_vscsi_fetch_desc_out_of_range(n, desc_offset);
                 return -1;
             }
             rc = spapr_vio_dma_read(&s->vdev, tbl_desc.va + desc_offset,
                                     ret, sizeof(struct srp_direct_buf));
             if (rc) {
-                DPRINTF("VSCSI: spapr_vio_dma_read -> %d reading ext_desc\n",
-                        rc);
+                trace_spapr_vscsi_fetch_desc_dma_read_error(rc);
                 return -1;
             }
-            DPRINTF("VSCSI: indirect segment ext. tag=0x%x desc#%d/%d { va=%"PRIx64" len=%x }\n",
-                    req->qtag, n, req->total_desc, tbl_desc.va, tbl_desc.len);
+            trace_spapr_vscsi_fetch_desc_indirect_seg_ext(req->qtag, n,
+                                                          req->total_desc,
+                                                          tbl_desc.va,
+                                                          tbl_desc.len);
         } else {
-            DPRINTF("VSCSI:   Out of descriptors !\n");
+            trace_spapr_vscsi_fetch_desc_out_of_desc();
             return 0;
         }
         break;
@@ -347,15 +347,16 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
 
     *ret = vscsi_swap_desc(*ret);
     if (buf_offset > ret->len) {
-        DPRINTF("   offset=%x is out of a descriptor #%d boundary=%x\n",
-                buf_offset, req->cur_desc_num, ret->len);
+        trace_spapr_vscsi_fetch_desc_out_of_desc_boundary(buf_offset,
+                                                          req->cur_desc_num,
+                                                          ret->len);
         return -1;
     }
     ret->va += buf_offset;
     ret->len -= buf_offset;
 
-    DPRINTF("   cur=%d offs=%x ret { va=%"PRIx64" len=%x }\n",
-            req->cur_desc_num, req->cur_desc_offset, ret->va, ret->len);
+    trace_spapr_vscsi_fetch_desc_done(req->cur_desc_num, req->cur_desc_offset,
+                                      ret->va, ret->len);
 
     return ret->len ? 1 : 0;
 }
@@ -398,7 +399,7 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
     int rc = 0;
     uint32_t llen, total = 0;
 
-    DPRINTF("VSCSI: indirect segment 0x%x bytes\n", len);
+    trace_spapr_vscsi_srp_indirect_data(len);
 
     /* While we have data ... */
     while (len) {
@@ -417,11 +418,10 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
             rc = spapr_vio_dma_write(&s->vdev, md.va, buf, llen);
         }
         if (rc) {
-            DPRINTF("VSCSI: spapr_vio_dma_r/w(%d) -> %d\n", req->writing, rc);
+            trace_spapr_vscsi_srp_indirect_data_rw(req->writing, rc);
             break;
         }
-        DPRINTF("VSCSI:     data: %02x %02x %02x %02x...\n",
-                buf[0], buf[1], buf[2], buf[3]);
+        trace_spapr_vscsi_srp_indirect_data_buf(buf[0], buf[1], buf[2], buf[3]);
 
         len -= llen;
         buf += llen;
@@ -447,7 +447,7 @@ static int vscsi_srp_transfer_data(VSCSIState *s, vscsi_req *req,
 
     switch (req->dma_fmt) {
     case SRP_NO_DATA_DESC:
-        DPRINTF("VSCSI: no data desc transfer, skipping 0x%x bytes\n", len);
+        trace_spapr_vscsi_srp_transfer_data(len);
         break;
     case SRP_DATA_DESC_DIRECT:
         err = vscsi_srp_direct_data(s, req, buf, len);
@@ -483,7 +483,7 @@ static int data_out_desc_size(struct srp_cmd *cmd)
 
 static int vscsi_preprocess_desc(vscsi_req *req)
 {
-    struct srp_cmd *cmd = &req->iu.srp.cmd;
+    struct srp_cmd *cmd = &req_iu(req)->srp.cmd;
 
     req->cdb_offset = cmd->add_cdb_len & ~3;
 
@@ -527,8 +527,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
     uint8_t *buf;
     int rc = 0;
 
-    DPRINTF("VSCSI: SCSI xfer complete tag=0x%x len=0x%x, req=%p\n",
-            sreq->tag, len, req);
+    trace_spapr_vscsi_transfer_data(sreq->tag, len, req);
     if (req == NULL) {
         fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
         return;
@@ -551,33 +550,31 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 }
 
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
-static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid)
+static void vscsi_command_complete(SCSIRequest *sreq, size_t resid)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
     vscsi_req *req = sreq->hba_private;
     int32_t res_in = 0, res_out = 0;
 
-    DPRINTF("VSCSI: SCSI cmd complete, tag=0x%x status=0x%x, req=%p\n",
-            sreq->tag, status, req);
+    trace_spapr_vscsi_command_complete(sreq->tag, sreq->status, req);
     if (req == NULL) {
         fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
         return;
     }
 
-    if (status == CHECK_CONDITION) {
+    if (sreq->status == CHECK_CONDITION) {
         req->senselen = scsi_req_get_sense(req->sreq, req->sense,
                                            sizeof(req->sense));
-        DPRINTF("VSCSI: Sense data, %d bytes:\n", req->senselen);
-        DPRINTF("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
+        trace_spapr_vscsi_command_complete_sense_data1(req->senselen,
                 req->sense[0], req->sense[1], req->sense[2], req->sense[3],
                 req->sense[4], req->sense[5], req->sense[6], req->sense[7]);
-        DPRINTF("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
+        trace_spapr_vscsi_command_complete_sense_data2(
                 req->sense[8], req->sense[9], req->sense[10], req->sense[11],
                 req->sense[12], req->sense[13], req->sense[14], req->sense[15]);
     }
 
-    DPRINTF("VSCSI: Command complete err=%d\n", status);
-    if (status == 0) {
+    trace_spapr_vscsi_command_complete_status(sreq->status);
+    if (sreq->status == 0) {
         /* We handle overflows, not underflows for normal commands,
          * but hopefully nobody cares
          */
@@ -587,7 +584,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t re
             res_in = req->data_len;
         }
     }
-    vscsi_send_rsp(s, req, status, res_in, res_out);
+    vscsi_send_rsp(s, req, sreq->status, res_in, res_out);
     vscsi_put_req(req);
 }
 
@@ -610,7 +607,7 @@ static const VMStateDescription vmstate_spapr_vscsi_req = {
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_BUFFER(crq.raw, vscsi_req),
-        VMSTATE_BUFFER(iu.srp.reserved, vscsi_req),
+        VMSTATE_BUFFER(viosrp_iu_buf, vscsi_req),
         VMSTATE_UINT32(qtag, vscsi_req),
         VMSTATE_BOOL(active, vscsi_req),
         VMSTATE_UINT32(data_len, vscsi_req),
@@ -635,8 +632,8 @@ static void vscsi_save_request(QEMUFile *f, SCSIRequest *sreq)
 
     vmstate_save_state(f, &vmstate_spapr_vscsi_req, req, NULL);
 
-    DPRINTF("VSCSI: saving tag=%u, current desc#%d, offset=%x\n",
-            req->qtag, req->cur_desc_num, req->cur_desc_offset);
+    trace_spapr_vscsi_save_request(req->qtag, req->cur_desc_num,
+                                   req->cur_desc_offset);
 }
 
 static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
@@ -660,19 +657,19 @@ static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
 
     req->sreq = scsi_req_ref(sreq);
 
-    DPRINTF("VSCSI: restoring tag=%u, current desc#%d, offset=%x\n",
-            req->qtag, req->cur_desc_num, req->cur_desc_offset);
+    trace_spapr_vscsi_load_request(req->qtag, req->cur_desc_num,
+                                   req->cur_desc_offset);
 
     return req;
 }
 
 static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
 {
-    union viosrp_iu *iu = &req->iu;
+    union viosrp_iu *iu = req_iu(req);
     struct srp_login_rsp *rsp = &iu->srp.login_rsp;
     uint64_t tag = iu->srp.rsp.tag;
 
-    DPRINTF("VSCSI: Got login, sendin response !\n");
+    trace_spapr_vscsi_process_login();
 
     /* TODO handle case that requested size is wrong and
      * buffer format is wrong
@@ -684,8 +681,8 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
      */
     rsp->req_lim_delta = cpu_to_be32(VSCSI_REQ_LIMIT-2);
     rsp->tag = tag;
-    rsp->max_it_iu_len = cpu_to_be32(sizeof(union srp_iu));
-    rsp->max_ti_iu_len = cpu_to_be32(sizeof(union srp_iu));
+    rsp->max_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+    rsp->max_ti_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
     /* direct and indirect */
     rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT);
 
@@ -694,11 +691,11 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
 
 static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req)
 {
-    uint8_t *cdb = req->iu.srp.cmd.cdb;
+    uint8_t *cdb = req_iu(req)->srp.cmd.cdb;
     uint8_t resp_data[36];
     int rc, len, alen;
 
-    /* We dont do EVPD. Also check that page_code is 0 */
+    /* We don't do EVPD. Also check that page_code is 0 */
     if ((cdb[1] & 0x01) || cdb[2] != 0) {
         /* Send INVALID FIELD IN CDB */
         vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x24, 0);
@@ -783,7 +780,7 @@ static void vscsi_report_luns(VSCSIState *s, vscsi_req *req)
 
 static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
 {
-    union srp_iu *srp = &req->iu.srp;
+    union srp_iu *srp = &req_iu(req)->srp;
     SCSIDevice *sdev;
     int n, lun;
 
@@ -795,8 +792,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
 
     sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
     if (!sdev) {
-        DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",
-                be64_to_cpu(srp->cmd.lun));
+        trace_spapr_vscsi_queue_cmd_no_drive(be64_to_cpu(srp->cmd.lun));
         if (srp->cmd.cdb[0] == INQUIRY) {
             vscsi_inquiry_no_target(s, req);
         } else {
@@ -808,9 +804,8 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
     req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, req);
     n = scsi_req_enqueue(req->sreq);
 
-    DPRINTF("VSCSI: Queued command tag 0x%x CMD 0x%x=%s LUN %d ret: %d\n",
-            req->qtag, srp->cmd.cdb[0], scsi_command_name(srp->cmd.cdb[0]),
-            lun, n);
+    trace_spapr_vscsi_queue_cmd(req->qtag, srp->cmd.cdb[0],
+                                scsi_command_name(srp->cmd.cdb[0]), lun, n);
 
     if (n) {
         /* Transfer direction must be set before preprocessing the
@@ -836,17 +831,16 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
 
 static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
 {
-    union viosrp_iu *iu = &req->iu;
+    union viosrp_iu *iu = req_iu(req);
     vscsi_req *tmpreq;
     int i, lun = 0, resp = SRP_TSK_MGMT_COMPLETE;
     SCSIDevice *d;
     uint64_t tag = iu->srp.rsp.tag;
     uint8_t sol_not = iu->srp.cmd.sol_not;
 
-    fprintf(stderr, "vscsi_process_tsk_mgmt %02x\n",
-            iu->srp.tsk_mgmt.tsk_mgmt_func);
-
-    d = vscsi_device_find(&s->bus, be64_to_cpu(req->iu.srp.tsk_mgmt.lun), &lun);
+    trace_spapr_vscsi_process_tsk_mgmt(iu->srp.tsk_mgmt.tsk_mgmt_func);
+    d = vscsi_device_find(&s->bus,
+                          be64_to_cpu(req_iu(req)->srp.tsk_mgmt.lun), &lun);
     if (!d) {
         resp = SRP_TSK_MGMT_FIELDS_INVALID;
     } else {
@@ -857,7 +851,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
                 break;
             }
 
-            tmpreq = vscsi_find_req(s, req->iu.srp.tsk_mgmt.task_tag);
+            tmpreq = vscsi_find_req(s, req_iu(req)->srp.tsk_mgmt.task_tag);
             if (tmpreq && tmpreq->sreq) {
                 assert(tmpreq->sreq->hba_private);
                 scsi_req_cancel(tmpreq->sreq);
@@ -882,7 +876,8 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
 
             for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
                 tmpreq = &s->reqs[i];
-                if (tmpreq->iu.srp.cmd.lun != req->iu.srp.tsk_mgmt.lun) {
+                if (req_iu(tmpreq)->srp.cmd.lun
+                        != req_iu(req)->srp.tsk_mgmt.lun) {
                     continue;
                 }
                 if (!tmpreq->active || !tmpreq->sreq) {
@@ -904,6 +899,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
     }
 
     /* Compose the response here as  */
+    QEMU_BUILD_BUG_ON(SRP_MAX_IU_DATA_LEN < 4);
     memset(iu, 0, sizeof(struct srp_rsp) + 4);
     iu->srp.rsp.opcode = SRP_RSP;
     iu->srp.rsp.req_lim_delta = cpu_to_be32(1);
@@ -926,7 +922,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
 
 static int vscsi_handle_srp_req(VSCSIState *s, vscsi_req *req)
 {
-    union srp_iu *srp = &req->iu.srp;
+    union srp_iu *srp = &req_iu(req)->srp;
     int done = 1;
     uint8_t opcode = srp->rsp.opcode;
 
@@ -963,7 +959,7 @@ static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req)
     struct mad_adapter_info_data info;
     int rc;
 
-    sinfo = &req->iu.mad.adapter_info;
+    sinfo = &req_iu(req)->mad.adapter_info;
 
 #if 0 /* What for ? */
     rc = spapr_vio_dma_read(&s->vdev, be64_to_cpu(sinfo->buffer),
@@ -999,7 +995,7 @@ static int vscsi_send_capabilities(VSCSIState *s, vscsi_req *req)
     uint64_t buffer;
     int rc;
 
-    vcap = &req->iu.mad.capabilities;
+    vcap = &req_iu(req)->mad.capabilities;
     req_len = len = be16_to_cpu(vcap->common.length);
     buffer = be64_to_cpu(vcap->buffer);
     if (len > sizeof(cap)) {
@@ -1044,7 +1040,7 @@ static int vscsi_send_capabilities(VSCSIState *s, vscsi_req *req)
 
 static int vscsi_handle_mad_req(VSCSIState *s, vscsi_req *req)
 {
-    union mad_iu *mad = &req->iu.mad;
+    union mad_iu *mad = &req_iu(req)->mad;
     bool request_handled = false;
     uint64_t retlen = 0;
 
@@ -1103,7 +1099,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
      * in our 256 bytes IUs. If not we'll have to increase the size
      * of the structure.
      */
-    if (crq->s.IU_length > sizeof(union viosrp_iu)) {
+    if (crq->s.IU_length > SRP_MAX_IU_LEN) {
         fprintf(stderr, "VSCSI: SRP IU too long (%d bytes) !\n",
                 crq->s.IU_length);
         vscsi_put_req(req);
@@ -1111,7 +1107,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
     }
 
     /* XXX Handle failure differently ? */
-    if (spapr_vio_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu,
+    if (spapr_vio_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->viosrp_iu_buf,
                            crq->s.IU_length)) {
         fprintf(stderr, "vscsi_got_payload: DMA read failure !\n");
         vscsi_put_req(req);
@@ -1131,7 +1127,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
 }
 
 
-static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
+static int vscsi_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     vscsi_crq crq;
@@ -1141,7 +1137,7 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
     crq.s.IU_length = be16_to_cpu(crq.s.IU_length);
     crq.s.IU_data_ptr = be64_to_cpu(crq.s.IU_data_ptr);
 
-    DPRINTF("VSCSI: do_crq %02x %02x ...\n", crq.raw[0], crq.raw[1]);
+    trace_spapr_vscsi_do_crq(crq.raw[0], crq.raw[1]);
 
     switch (crq.s.valid) {
     case 0xc0: /* Init command/response */
@@ -1203,7 +1199,7 @@ static const struct SCSIBusInfo vscsi_scsi_info = {
     .load_request = vscsi_load_request,
 };
 
-static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
+static void spapr_vscsi_reset(SpaprVioDevice *dev)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     int i;
@@ -1214,7 +1210,7 @@ static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
     }
 }
 
-static void spapr_vscsi_realize(VIOsPAPRDevice *dev, Error **errp)
+static void spapr_vscsi_realize(SpaprVioDevice *dev, Error **errp)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
 
@@ -1222,21 +1218,22 @@ static void spapr_vscsi_realize(VIOsPAPRDevice *dev, Error **errp)
 
     scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
                  &vscsi_scsi_info, NULL);
-    if (!dev->qdev.hotplugged) {
-        scsi_bus_legacy_handle_cmdline(&s->bus, errp);
-    }
+
+    /* ibmvscsi SCSI bus does not allow hotplug. */
+    qbus_set_hotplug_handler(BUS(&s->bus), NULL);
 }
 
-void spapr_vscsi_create(VIOsPAPRBus *bus)
+void spapr_vscsi_create(SpaprVioBus *bus)
 {
     DeviceState *dev;
 
-    dev = qdev_create(&bus->bus, "spapr-vscsi");
+    dev = qdev_new("spapr-vscsi");
 
-    qdev_init_nofail(dev);
+    qdev_realize_and_unref(dev, &bus->bus, &error_fatal);
+    scsi_bus_legacy_handle_cmdline(&VIO_SPAPR_VSCSI_DEVICE(dev)->bus);
 }
 
-static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+static int spapr_vscsi_devnode(SpaprVioDevice *dev, void *fdt, int node_off)
 {
     int ret;
 
@@ -1274,7 +1271,7 @@ static const VMStateDescription vmstate_spapr_vscsi = {
 static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+    SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->realize = spapr_vscsi_realize;
     k->reset = spapr_vscsi_reset;
@@ -1284,7 +1281,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
     k->dt_compatible = "IBM,v-scsi";
     k->signal_mask = 0x00000001;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = spapr_vscsi_properties;
+    device_class_set_props(dc, spapr_vscsi_properties);
     k->rtce_window_size = 0x10000000;
     dc->vmsd = &vmstate_spapr_vscsi;
 }