Message ID | 1364519296-31883-2-git-send-email-nab@linux-iscsi.org |
---|---|
State | New |
Headers | show |
"Nicholas A. Bellinger" <nab@linux-iscsi.org> writes: > From: Paolo Bonzini <pbonzini@redhat.com> > > This patch refactors existing virtio-scsi code into VirtIOSCSICommon > in order to allow virtio_scsi_init_common() to be used by both internal > virtio_scsi_init() and external vhost-scsi-pci code. > > Changes in Patch-v2: > - Move ->get_features() assignment to virtio_scsi_init() instead of > virtio_scsi_init_common() Any reason we're not doing this as a QOM base class? Similiar to how the in-kernel PIT/PIC work using a common base class... Regards, Anthony Liguori > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > Cc: Michael S. Tsirkin <mst@redhat.com> > Cc: Asias He <asias@redhat.com> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> > --- > hw/virtio-scsi.c | 192 +++++++++++++------------------------------------- > hw/virtio-scsi.h | 130 ++++++++++++++++++++++++++++++++-- > include/qemu/osdep.h | 4 + > 3 files changed, 178 insertions(+), 148 deletions(-) > > diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c > index 8620712..c59e9c6 100644 > --- a/hw/virtio-scsi.c > +++ b/hw/virtio-scsi.c > @@ -18,118 +18,6 @@ > #include <hw/scsi.h> > #include <hw/scsi-defs.h> > > -#define VIRTIO_SCSI_VQ_SIZE 128 > -#define VIRTIO_SCSI_CDB_SIZE 32 > -#define VIRTIO_SCSI_SENSE_SIZE 96 > -#define VIRTIO_SCSI_MAX_CHANNEL 0 > -#define VIRTIO_SCSI_MAX_TARGET 255 > -#define VIRTIO_SCSI_MAX_LUN 16383 > - > -/* Response codes */ > -#define VIRTIO_SCSI_S_OK 0 > -#define VIRTIO_SCSI_S_OVERRUN 1 > -#define VIRTIO_SCSI_S_ABORTED 2 > -#define VIRTIO_SCSI_S_BAD_TARGET 3 > -#define VIRTIO_SCSI_S_RESET 4 > -#define VIRTIO_SCSI_S_BUSY 5 > -#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 > -#define VIRTIO_SCSI_S_TARGET_FAILURE 7 > -#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 > -#define VIRTIO_SCSI_S_FAILURE 9 > -#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 > -#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 > -#define VIRTIO_SCSI_S_INCORRECT_LUN 12 > - > -/* Controlq type codes. */ > -#define VIRTIO_SCSI_T_TMF 0 > -#define VIRTIO_SCSI_T_AN_QUERY 1 > -#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 > - > -/* Valid TMF subtypes. */ > -#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 > -#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 > -#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 > -#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 > -#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 > -#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 > -#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 > -#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 > - > -/* Events. */ > -#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 > -#define VIRTIO_SCSI_T_NO_EVENT 0 > -#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 > -#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 > -#define VIRTIO_SCSI_T_PARAM_CHANGE 3 > - > -/* Reasons for transport reset event */ > -#define VIRTIO_SCSI_EVT_RESET_HARD 0 > -#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 > -#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 > - > -/* SCSI command request, followed by data-out */ > -typedef struct { > - uint8_t lun[8]; /* Logical Unit Number */ > - uint64_t tag; /* Command identifier */ > - uint8_t task_attr; /* Task attribute */ > - uint8_t prio; > - uint8_t crn; > - uint8_t cdb[]; > -} QEMU_PACKED VirtIOSCSICmdReq; > - > -/* Response, followed by sense data and data-in */ > -typedef struct { > - uint32_t sense_len; /* Sense data length */ > - uint32_t resid; /* Residual bytes in data buffer */ > - uint16_t status_qualifier; /* Status qualifier */ > - uint8_t status; /* Command completion status */ > - uint8_t response; /* Response values */ > - uint8_t sense[]; > -} QEMU_PACKED VirtIOSCSICmdResp; > - > -/* Task Management Request */ > -typedef struct { > - uint32_t type; > - uint32_t subtype; > - uint8_t lun[8]; > - uint64_t tag; > -} QEMU_PACKED VirtIOSCSICtrlTMFReq; > - > -typedef struct { > - uint8_t response; > -} QEMU_PACKED VirtIOSCSICtrlTMFResp; > - > -/* Asynchronous notification query/subscription */ > -typedef struct { > - uint32_t type; > - uint8_t lun[8]; > - uint32_t event_requested; > -} QEMU_PACKED VirtIOSCSICtrlANReq; > - > -typedef struct { > - uint32_t event_actual; > - uint8_t response; > -} QEMU_PACKED VirtIOSCSICtrlANResp; > - > -typedef struct { > - uint32_t event; > - uint8_t lun[8]; > - uint32_t reason; > -} QEMU_PACKED VirtIOSCSIEvent; > - > -typedef struct { > - uint32_t num_queues; > - uint32_t seg_max; > - uint32_t max_sectors; > - uint32_t cmd_per_lun; > - uint32_t event_info_size; > - uint32_t sense_size; > - uint32_t cdb_size; > - uint16_t max_channel; > - uint16_t max_target; > - uint32_t max_lun; > -} QEMU_PACKED VirtIOSCSIConfig; > - > typedef struct VirtIOSCSIReq { > VirtIOSCSI *dev; > VirtQueue *vq; > @@ -178,7 +66,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req) > scsi_req_unref(req->sreq); > } > g_free(req); > - virtio_notify(&s->vdev, vq); > + virtio_notify(&s->vs.vdev, vq); > } > > static void virtio_scsi_bad_req(void) > @@ -237,7 +125,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq) > VirtIOSCSIReq *req = sreq->hba_private; > uint32_t n = virtio_queue_get_id(req->vq) - 2; > > - assert(n < req->dev->conf->num_queues); > + assert(n < req->dev->vs.conf->num_queues); > qemu_put_be32s(f, &n); > qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); > } > @@ -251,9 +139,9 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq) > > req = g_malloc(sizeof(*req)); > qemu_get_be32s(f, &n); > - assert(n < s->conf->num_queues); > + assert(n < s->vs.conf->num_queues); > qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); > - virtio_scsi_parse_req(s, s->cmd_vqs[n], req); > + virtio_scsi_parse_req(s, s->vs.cmd_vqs[n], req); > > scsi_req_ref(sreq); > req->sreq = sreq; > @@ -468,8 +356,8 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) > > out_size = req->elem.out_sg[0].iov_len; > in_size = req->elem.in_sg[0].iov_len; > - if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size || > - in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) { > + if (out_size < sizeof(VirtIOSCSICmdReq) + s->vs.cdb_size || > + in_size < sizeof(VirtIOSCSICmdResp) + s->vs.sense_size) { > virtio_scsi_bad_req(); > } > > @@ -511,7 +399,7 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, > uint8_t *config) > { > VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config; > - VirtIOSCSI *s = (VirtIOSCSI *)vdev; > + VirtIOSCSICommon *s = (VirtIOSCSICommon *)vdev; > > stl_raw(&scsiconf->num_queues, s->conf->num_queues); > stl_raw(&scsiconf->seg_max, 128 - 2); > @@ -537,8 +425,8 @@ static void virtio_scsi_set_config(VirtIODevice *vdev, > exit(1); > } > > - s->sense_size = ldl_raw(&scsiconf->sense_size); > - s->cdb_size = ldl_raw(&scsiconf->cdb_size); > + s->vs.sense_size = ldl_raw(&scsiconf->sense_size); > + s->vs.cdb_size = ldl_raw(&scsiconf->cdb_size); > } > > static uint32_t virtio_scsi_get_features(VirtIODevice *vdev, > @@ -555,8 +443,8 @@ static void virtio_scsi_reset(VirtIODevice *vdev) > qbus_reset_all(&s->bus.qbus); > s->resetting--; > > - s->sense_size = VIRTIO_SCSI_SENSE_SIZE; > - s->cdb_size = VIRTIO_SCSI_CDB_SIZE; > + s->vs.sense_size = VIRTIO_SCSI_SENSE_SIZE; > + s->vs.cdb_size = VIRTIO_SCSI_CDB_SIZE; > s->events_dropped = false; > } > > @@ -566,7 +454,7 @@ static void virtio_scsi_reset(VirtIODevice *vdev) > static void virtio_scsi_save(QEMUFile *f, void *opaque) > { > VirtIOSCSI *s = opaque; > - virtio_save(&s->vdev, f); > + virtio_save(&s->vs.vdev, f); > } > > static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) > @@ -574,7 +462,7 @@ static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) > VirtIOSCSI *s = opaque; > int ret; > > - ret = virtio_load(&s->vdev, f); > + ret = virtio_load(&s->vs.vdev, f); > if (ret) { > return ret; > } > @@ -584,11 +472,11 @@ static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) > static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, > uint32_t event, uint32_t reason) > { > - VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq); > + VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->vs.event_vq); > VirtIOSCSIEvent *evt; > int in_size; > > - if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { > + if (!(s->vs.vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { > return; > } > > @@ -643,7 +531,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) > { > VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); > > - if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && > + if (((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && > dev->type != TYPE_ROM) { > virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, > sense.asc | (sense.ascq << 8)); > @@ -654,7 +542,7 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) > { > VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); > > - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { > + if ((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { > virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, > VIRTIO_SCSI_EVT_RESET_RESCAN); > } > @@ -664,7 +552,7 @@ static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev) > { > VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); > > - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { > + if ((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { > virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, > VIRTIO_SCSI_EVT_RESET_REMOVED); > } > @@ -686,35 +574,53 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = { > .load_request = virtio_scsi_load_request, > }; > > -VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) > +VirtIOSCSICommon *virtio_scsi_init_common(DeviceState *dev, VirtIOSCSIConf *proxyconf, > + size_t sz) > { > - VirtIOSCSI *s; > - static int virtio_scsi_id; > - size_t sz; > + VirtIOSCSICommon *s; > int i; > > - sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *); > - s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI, > - sizeof(VirtIOSCSIConfig), sz); > + /* Place the cmd_vqs array at the end of the block that the caller > + * requested. Align the array properly, just in case. > + */ > + sz = ROUND_UP(sz, sizeof(void *)); > + s = (VirtIOSCSICommon *) > + virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI, > + sizeof(VirtIOSCSIConfig), > + sz + sizeof(VirtQueue *) * proxyconf->num_queues); > > s->qdev = dev; > s->conf = proxyconf; > + s->sense_size = VIRTIO_SCSI_SENSE_SIZE; > + s->cdb_size = VIRTIO_SCSI_CDB_SIZE; > > - /* TODO set up vdev function pointers */ > s->vdev.get_config = virtio_scsi_get_config; > - s->vdev.set_config = virtio_scsi_set_config; > - s->vdev.get_features = virtio_scsi_get_features; > - s->vdev.reset = virtio_scsi_reset; > > s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, > virtio_scsi_handle_ctrl); > s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, > virtio_scsi_handle_event); > + > + s->cmd_vqs = (VirtQueue **) ((char *)s + sz); > for (i = 0; i < s->conf->num_queues; i++) { > s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, > virtio_scsi_handle_cmd); > } > > + return s; > +} > + > +VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) > +{ > + VirtIOSCSI *s; > + static int virtio_scsi_id; > + > + s = (VirtIOSCSI *)virtio_scsi_init_common(dev, proxyconf, sizeof(VirtIOSCSI)); > + > + s->vs.vdev.get_features = virtio_scsi_get_features; > + s->vs.vdev.set_config = virtio_scsi_set_config; > + s->vs.vdev.reset = virtio_scsi_reset; > + > scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info); > if (!dev->hotplugged) { > scsi_bus_legacy_handle_cmdline(&s->bus); > @@ -723,12 +629,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) > register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1, > virtio_scsi_save, virtio_scsi_load, s); > > - return &s->vdev; > + return &s->vs.vdev; > } > > void virtio_scsi_exit(VirtIODevice *vdev) > { > VirtIOSCSI *s = (VirtIOSCSI *)vdev; > - unregister_savevm(s->qdev, "virtio-scsi", s); > + unregister_savevm(s->vs.qdev, "virtio-scsi", s); > virtio_cleanup(vdev); > } > diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h > index ccf1e42..2bcf606 100644 > --- a/hw/virtio-scsi.h > +++ b/hw/virtio-scsi.h > @@ -26,25 +26,142 @@ > #define VIRTIO_SCSI_F_HOTPLUG 1 > #define VIRTIO_SCSI_F_CHANGE 2 > > +#define VIRTIO_SCSI_VQ_SIZE 128 > +#define VIRTIO_SCSI_CDB_SIZE 32 > +#define VIRTIO_SCSI_SENSE_SIZE 96 > +#define VIRTIO_SCSI_MAX_CHANNEL 0 > +#define VIRTIO_SCSI_MAX_TARGET 255 > +#define VIRTIO_SCSI_MAX_LUN 16383 > + > +/* Response codes */ > +#define VIRTIO_SCSI_S_OK 0 > +#define VIRTIO_SCSI_S_OVERRUN 1 > +#define VIRTIO_SCSI_S_ABORTED 2 > +#define VIRTIO_SCSI_S_BAD_TARGET 3 > +#define VIRTIO_SCSI_S_RESET 4 > +#define VIRTIO_SCSI_S_BUSY 5 > +#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 > +#define VIRTIO_SCSI_S_TARGET_FAILURE 7 > +#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 > +#define VIRTIO_SCSI_S_FAILURE 9 > +#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 > +#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 > +#define VIRTIO_SCSI_S_INCORRECT_LUN 12 > + > +/* Controlq type codes. */ > +#define VIRTIO_SCSI_T_TMF 0 > +#define VIRTIO_SCSI_T_AN_QUERY 1 > +#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 > + > +/* Valid TMF subtypes. */ > +#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 > +#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 > +#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 > +#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 > +#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 > +#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 > +#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 > +#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 > + > +/* Events. */ > +#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 > +#define VIRTIO_SCSI_T_NO_EVENT 0 > +#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 > +#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 > +#define VIRTIO_SCSI_T_PARAM_CHANGE 3 > + > +/* Reasons for transport reset event */ > +#define VIRTIO_SCSI_EVT_RESET_HARD 0 > +#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 > +#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 > + > +/* SCSI command request, followed by data-out */ > +typedef struct { > + uint8_t lun[8]; /* Logical Unit Number */ > + uint64_t tag; /* Command identifier */ > + uint8_t task_attr; /* Task attribute */ > + uint8_t prio; > + uint8_t crn; > + uint8_t cdb[]; > +} QEMU_PACKED VirtIOSCSICmdReq; > + > +/* Response, followed by sense data and data-in */ > +typedef struct { > + uint32_t sense_len; /* Sense data length */ > + uint32_t resid; /* Residual bytes in data buffer */ > + uint16_t status_qualifier; /* Status qualifier */ > + uint8_t status; /* Command completion status */ > + uint8_t response; /* Response values */ > + uint8_t sense[]; > +} QEMU_PACKED VirtIOSCSICmdResp; > + > +/* Task Management Request */ > +typedef struct { > + uint32_t type; > + uint32_t subtype; > + uint8_t lun[8]; > + uint64_t tag; > +} QEMU_PACKED VirtIOSCSICtrlTMFReq; > + > +typedef struct { > + uint8_t response; > +} QEMU_PACKED VirtIOSCSICtrlTMFResp; > + > +/* Asynchronous notification query/subscription */ > +typedef struct { > + uint32_t type; > + uint8_t lun[8]; > + uint32_t event_requested; > +} QEMU_PACKED VirtIOSCSICtrlANReq; > + > +typedef struct { > + uint32_t event_actual; > + uint8_t response; > +} QEMU_PACKED VirtIOSCSICtrlANResp; > + > +typedef struct { > + uint32_t event; > + uint8_t lun[8]; > + uint32_t reason; > +} QEMU_PACKED VirtIOSCSIEvent; > + > +typedef struct { > + uint32_t num_queues; > + uint32_t seg_max; > + uint32_t max_sectors; > + uint32_t cmd_per_lun; > + uint32_t event_info_size; > + uint32_t sense_size; > + uint32_t cdb_size; > + uint16_t max_channel; > + uint16_t max_target; > + uint32_t max_lun; > +} QEMU_PACKED VirtIOSCSIConfig; > + > struct VirtIOSCSIConf { > uint32_t num_queues; > uint32_t max_sectors; > uint32_t cmd_per_lun; > }; > > -typedef struct VirtIOSCSI { > +typedef struct VirtIOSCSICommon { > VirtIODevice vdev; > DeviceState *qdev; > VirtIOSCSIConf *conf; > > - SCSIBus bus; > uint32_t sense_size; > uint32_t cdb_size; > - int resetting; > - bool events_dropped; > VirtQueue *ctrl_vq; > VirtQueue *event_vq; > - VirtQueue *cmd_vqs[0]; > + VirtQueue **cmd_vqs; > +} VirtIOSCSICommon; > + > +typedef struct { > + VirtIOSCSICommon vs; > + > + SCSIBus bus; > + int resetting; > + bool events_dropped; > } VirtIOSCSI; > > #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \ > @@ -55,4 +172,7 @@ typedef struct VirtIOSCSI { > DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \ > DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true) > > +VirtIOSCSICommon *virtio_scsi_init_common(DeviceState *dev, VirtIOSCSIConf *proxyconf, > + size_t sz); > + > #endif /* _QEMU_VIRTIO_SCSI_H */ > diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h > index df24400..8b465fd 100644 > --- a/include/qemu/osdep.h > +++ b/include/qemu/osdep.h > @@ -67,6 +67,10 @@ typedef signed int int_fast16_t; > #define MAX(a, b) (((a) > (b)) ? (a) : (b)) > #endif > > +#ifndef ROUND_UP > +#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d)) > +#endif > + > #ifndef DIV_ROUND_UP > #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) > #endif > -- > 1.7.2.5 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2013-04-08 at 16:59 -0500, Anthony Liguori wrote: > "Nicholas A. Bellinger" <nab@linux-iscsi.org> writes: > > > From: Paolo Bonzini <pbonzini@redhat.com> > > > > This patch refactors existing virtio-scsi code into VirtIOSCSICommon > > in order to allow virtio_scsi_init_common() to be used by both internal > > virtio_scsi_init() and external vhost-scsi-pci code. > > > > Changes in Patch-v2: > > - Move ->get_features() assignment to virtio_scsi_init() instead of > > virtio_scsi_init_common() > > > Any reason we're not doing this as a QOM base class? > > Similiar to how the in-kernel PIT/PIC work using a common base class... > Mmm, not sure. Paolo, what do you prefer here..? Also, has your qemu/scsi-next branch with this series been pushed to a public tree yet..? ;) --nab
Il 08/04/2013 23:59, Anthony Liguori ha scritto: > > This patch refactors existing virtio-scsi code into VirtIOSCSICommon > > in order to allow virtio_scsi_init_common() to be used by both internal > > virtio_scsi_init() and external vhost-scsi-pci code. > > > > Changes in Patch-v2: > > - Move ->get_features() assignment to virtio_scsi_init() instead of > > virtio_scsi_init_common() > > Any reason we're not doing this as a QOM base class? > > Similiar to how the in-kernel PIT/PIC work using a common base class... Because when the patch was written virtio-scsi was not a QOM class. Paolo
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 8620712..c59e9c6 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -18,118 +18,6 @@ #include <hw/scsi.h> #include <hw/scsi-defs.h> -#define VIRTIO_SCSI_VQ_SIZE 128 -#define VIRTIO_SCSI_CDB_SIZE 32 -#define VIRTIO_SCSI_SENSE_SIZE 96 -#define VIRTIO_SCSI_MAX_CHANNEL 0 -#define VIRTIO_SCSI_MAX_TARGET 255 -#define VIRTIO_SCSI_MAX_LUN 16383 - -/* Response codes */ -#define VIRTIO_SCSI_S_OK 0 -#define VIRTIO_SCSI_S_OVERRUN 1 -#define VIRTIO_SCSI_S_ABORTED 2 -#define VIRTIO_SCSI_S_BAD_TARGET 3 -#define VIRTIO_SCSI_S_RESET 4 -#define VIRTIO_SCSI_S_BUSY 5 -#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 -#define VIRTIO_SCSI_S_TARGET_FAILURE 7 -#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 -#define VIRTIO_SCSI_S_FAILURE 9 -#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 -#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 -#define VIRTIO_SCSI_S_INCORRECT_LUN 12 - -/* Controlq type codes. */ -#define VIRTIO_SCSI_T_TMF 0 -#define VIRTIO_SCSI_T_AN_QUERY 1 -#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 - -/* Valid TMF subtypes. */ -#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 -#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 -#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 -#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 -#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 -#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 - -/* Events. */ -#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 -#define VIRTIO_SCSI_T_NO_EVENT 0 -#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 -#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 -#define VIRTIO_SCSI_T_PARAM_CHANGE 3 - -/* Reasons for transport reset event */ -#define VIRTIO_SCSI_EVT_RESET_HARD 0 -#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 -#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 - -/* SCSI command request, followed by data-out */ -typedef struct { - uint8_t lun[8]; /* Logical Unit Number */ - uint64_t tag; /* Command identifier */ - uint8_t task_attr; /* Task attribute */ - uint8_t prio; - uint8_t crn; - uint8_t cdb[]; -} QEMU_PACKED VirtIOSCSICmdReq; - -/* Response, followed by sense data and data-in */ -typedef struct { - uint32_t sense_len; /* Sense data length */ - uint32_t resid; /* Residual bytes in data buffer */ - uint16_t status_qualifier; /* Status qualifier */ - uint8_t status; /* Command completion status */ - uint8_t response; /* Response values */ - uint8_t sense[]; -} QEMU_PACKED VirtIOSCSICmdResp; - -/* Task Management Request */ -typedef struct { - uint32_t type; - uint32_t subtype; - uint8_t lun[8]; - uint64_t tag; -} QEMU_PACKED VirtIOSCSICtrlTMFReq; - -typedef struct { - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlTMFResp; - -/* Asynchronous notification query/subscription */ -typedef struct { - uint32_t type; - uint8_t lun[8]; - uint32_t event_requested; -} QEMU_PACKED VirtIOSCSICtrlANReq; - -typedef struct { - uint32_t event_actual; - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlANResp; - -typedef struct { - uint32_t event; - uint8_t lun[8]; - uint32_t reason; -} QEMU_PACKED VirtIOSCSIEvent; - -typedef struct { - uint32_t num_queues; - uint32_t seg_max; - uint32_t max_sectors; - uint32_t cmd_per_lun; - uint32_t event_info_size; - uint32_t sense_size; - uint32_t cdb_size; - uint16_t max_channel; - uint16_t max_target; - uint32_t max_lun; -} QEMU_PACKED VirtIOSCSIConfig; - typedef struct VirtIOSCSIReq { VirtIOSCSI *dev; VirtQueue *vq; @@ -178,7 +66,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req) scsi_req_unref(req->sreq); } g_free(req); - virtio_notify(&s->vdev, vq); + virtio_notify(&s->vs.vdev, vq); } static void virtio_scsi_bad_req(void) @@ -237,7 +125,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq) VirtIOSCSIReq *req = sreq->hba_private; uint32_t n = virtio_queue_get_id(req->vq) - 2; - assert(n < req->dev->conf->num_queues); + assert(n < req->dev->vs.conf->num_queues); qemu_put_be32s(f, &n); qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); } @@ -251,9 +139,9 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq) req = g_malloc(sizeof(*req)); qemu_get_be32s(f, &n); - assert(n < s->conf->num_queues); + assert(n < s->vs.conf->num_queues); qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); - virtio_scsi_parse_req(s, s->cmd_vqs[n], req); + virtio_scsi_parse_req(s, s->vs.cmd_vqs[n], req); scsi_req_ref(sreq); req->sreq = sreq; @@ -468,8 +356,8 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) out_size = req->elem.out_sg[0].iov_len; in_size = req->elem.in_sg[0].iov_len; - if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size || - in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) { + if (out_size < sizeof(VirtIOSCSICmdReq) + s->vs.cdb_size || + in_size < sizeof(VirtIOSCSICmdResp) + s->vs.sense_size) { virtio_scsi_bad_req(); } @@ -511,7 +399,7 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, uint8_t *config) { VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config; - VirtIOSCSI *s = (VirtIOSCSI *)vdev; + VirtIOSCSICommon *s = (VirtIOSCSICommon *)vdev; stl_raw(&scsiconf->num_queues, s->conf->num_queues); stl_raw(&scsiconf->seg_max, 128 - 2); @@ -537,8 +425,8 @@ static void virtio_scsi_set_config(VirtIODevice *vdev, exit(1); } - s->sense_size = ldl_raw(&scsiconf->sense_size); - s->cdb_size = ldl_raw(&scsiconf->cdb_size); + s->vs.sense_size = ldl_raw(&scsiconf->sense_size); + s->vs.cdb_size = ldl_raw(&scsiconf->cdb_size); } static uint32_t virtio_scsi_get_features(VirtIODevice *vdev, @@ -555,8 +443,8 @@ static void virtio_scsi_reset(VirtIODevice *vdev) qbus_reset_all(&s->bus.qbus); s->resetting--; - s->sense_size = VIRTIO_SCSI_SENSE_SIZE; - s->cdb_size = VIRTIO_SCSI_CDB_SIZE; + s->vs.sense_size = VIRTIO_SCSI_SENSE_SIZE; + s->vs.cdb_size = VIRTIO_SCSI_CDB_SIZE; s->events_dropped = false; } @@ -566,7 +454,7 @@ static void virtio_scsi_reset(VirtIODevice *vdev) static void virtio_scsi_save(QEMUFile *f, void *opaque) { VirtIOSCSI *s = opaque; - virtio_save(&s->vdev, f); + virtio_save(&s->vs.vdev, f); } static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) @@ -574,7 +462,7 @@ static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) VirtIOSCSI *s = opaque; int ret; - ret = virtio_load(&s->vdev, f); + ret = virtio_load(&s->vs.vdev, f); if (ret) { return ret; } @@ -584,11 +472,11 @@ static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, uint32_t event, uint32_t reason) { - VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq); + VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->vs.event_vq); VirtIOSCSIEvent *evt; int in_size; - if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { + if (!(s->vs.vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { return; } @@ -643,7 +531,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && + if (((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -654,7 +542,7 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if ((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } @@ -664,7 +552,7 @@ static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if ((s->vs.vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } @@ -686,35 +574,53 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = { .load_request = virtio_scsi_load_request, }; -VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) +VirtIOSCSICommon *virtio_scsi_init_common(DeviceState *dev, VirtIOSCSIConf *proxyconf, + size_t sz) { - VirtIOSCSI *s; - static int virtio_scsi_id; - size_t sz; + VirtIOSCSICommon *s; int i; - sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *); - s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI, - sizeof(VirtIOSCSIConfig), sz); + /* Place the cmd_vqs array at the end of the block that the caller + * requested. Align the array properly, just in case. + */ + sz = ROUND_UP(sz, sizeof(void *)); + s = (VirtIOSCSICommon *) + virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI, + sizeof(VirtIOSCSIConfig), + sz + sizeof(VirtQueue *) * proxyconf->num_queues); s->qdev = dev; s->conf = proxyconf; + s->sense_size = VIRTIO_SCSI_SENSE_SIZE; + s->cdb_size = VIRTIO_SCSI_CDB_SIZE; - /* TODO set up vdev function pointers */ s->vdev.get_config = virtio_scsi_get_config; - s->vdev.set_config = virtio_scsi_set_config; - s->vdev.get_features = virtio_scsi_get_features; - s->vdev.reset = virtio_scsi_reset; s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, virtio_scsi_handle_ctrl); s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, virtio_scsi_handle_event); + + s->cmd_vqs = (VirtQueue **) ((char *)s + sz); for (i = 0; i < s->conf->num_queues; i++) { s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, virtio_scsi_handle_cmd); } + return s; +} + +VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) +{ + VirtIOSCSI *s; + static int virtio_scsi_id; + + s = (VirtIOSCSI *)virtio_scsi_init_common(dev, proxyconf, sizeof(VirtIOSCSI)); + + s->vs.vdev.get_features = virtio_scsi_get_features; + s->vs.vdev.set_config = virtio_scsi_set_config; + s->vs.vdev.reset = virtio_scsi_reset; + scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info); if (!dev->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus); @@ -723,12 +629,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1, virtio_scsi_save, virtio_scsi_load, s); - return &s->vdev; + return &s->vs.vdev; } void virtio_scsi_exit(VirtIODevice *vdev) { VirtIOSCSI *s = (VirtIOSCSI *)vdev; - unregister_savevm(s->qdev, "virtio-scsi", s); + unregister_savevm(s->vs.qdev, "virtio-scsi", s); virtio_cleanup(vdev); } diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index ccf1e42..2bcf606 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -26,25 +26,142 @@ #define VIRTIO_SCSI_F_HOTPLUG 1 #define VIRTIO_SCSI_F_CHANGE 2 +#define VIRTIO_SCSI_VQ_SIZE 128 +#define VIRTIO_SCSI_CDB_SIZE 32 +#define VIRTIO_SCSI_SENSE_SIZE 96 +#define VIRTIO_SCSI_MAX_CHANNEL 0 +#define VIRTIO_SCSI_MAX_TARGET 255 +#define VIRTIO_SCSI_MAX_LUN 16383 + +/* Response codes */ +#define VIRTIO_SCSI_S_OK 0 +#define VIRTIO_SCSI_S_OVERRUN 1 +#define VIRTIO_SCSI_S_ABORTED 2 +#define VIRTIO_SCSI_S_BAD_TARGET 3 +#define VIRTIO_SCSI_S_RESET 4 +#define VIRTIO_SCSI_S_BUSY 5 +#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 +#define VIRTIO_SCSI_S_TARGET_FAILURE 7 +#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 +#define VIRTIO_SCSI_S_FAILURE 9 +#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 +#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 +#define VIRTIO_SCSI_S_INCORRECT_LUN 12 + +/* Controlq type codes. */ +#define VIRTIO_SCSI_T_TMF 0 +#define VIRTIO_SCSI_T_AN_QUERY 1 +#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 + +/* Valid TMF subtypes. */ +#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 +#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 +#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 +#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 +#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 +#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 +#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 +#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 + +/* Events. */ +#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 +#define VIRTIO_SCSI_T_NO_EVENT 0 +#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 +#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 +#define VIRTIO_SCSI_T_PARAM_CHANGE 3 + +/* Reasons for transport reset event */ +#define VIRTIO_SCSI_EVT_RESET_HARD 0 +#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 +#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 + +/* SCSI command request, followed by data-out */ +typedef struct { + uint8_t lun[8]; /* Logical Unit Number */ + uint64_t tag; /* Command identifier */ + uint8_t task_attr; /* Task attribute */ + uint8_t prio; + uint8_t crn; + uint8_t cdb[]; +} QEMU_PACKED VirtIOSCSICmdReq; + +/* Response, followed by sense data and data-in */ +typedef struct { + uint32_t sense_len; /* Sense data length */ + uint32_t resid; /* Residual bytes in data buffer */ + uint16_t status_qualifier; /* Status qualifier */ + uint8_t status; /* Command completion status */ + uint8_t response; /* Response values */ + uint8_t sense[]; +} QEMU_PACKED VirtIOSCSICmdResp; + +/* Task Management Request */ +typedef struct { + uint32_t type; + uint32_t subtype; + uint8_t lun[8]; + uint64_t tag; +} QEMU_PACKED VirtIOSCSICtrlTMFReq; + +typedef struct { + uint8_t response; +} QEMU_PACKED VirtIOSCSICtrlTMFResp; + +/* Asynchronous notification query/subscription */ +typedef struct { + uint32_t type; + uint8_t lun[8]; + uint32_t event_requested; +} QEMU_PACKED VirtIOSCSICtrlANReq; + +typedef struct { + uint32_t event_actual; + uint8_t response; +} QEMU_PACKED VirtIOSCSICtrlANResp; + +typedef struct { + uint32_t event; + uint8_t lun[8]; + uint32_t reason; +} QEMU_PACKED VirtIOSCSIEvent; + +typedef struct { + uint32_t num_queues; + uint32_t seg_max; + uint32_t max_sectors; + uint32_t cmd_per_lun; + uint32_t event_info_size; + uint32_t sense_size; + uint32_t cdb_size; + uint16_t max_channel; + uint16_t max_target; + uint32_t max_lun; +} QEMU_PACKED VirtIOSCSIConfig; + struct VirtIOSCSIConf { uint32_t num_queues; uint32_t max_sectors; uint32_t cmd_per_lun; }; -typedef struct VirtIOSCSI { +typedef struct VirtIOSCSICommon { VirtIODevice vdev; DeviceState *qdev; VirtIOSCSIConf *conf; - SCSIBus bus; uint32_t sense_size; uint32_t cdb_size; - int resetting; - bool events_dropped; VirtQueue *ctrl_vq; VirtQueue *event_vq; - VirtQueue *cmd_vqs[0]; + VirtQueue **cmd_vqs; +} VirtIOSCSICommon; + +typedef struct { + VirtIOSCSICommon vs; + + SCSIBus bus; + int resetting; + bool events_dropped; } VirtIOSCSI; #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \ @@ -55,4 +172,7 @@ typedef struct VirtIOSCSI { DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \ DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true) +VirtIOSCSICommon *virtio_scsi_init_common(DeviceState *dev, VirtIOSCSIConf *proxyconf, + size_t sz); + #endif /* _QEMU_VIRTIO_SCSI_H */ diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index df24400..8b465fd 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -67,6 +67,10 @@ typedef signed int int_fast16_t; #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif +#ifndef ROUND_UP +#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d)) +#endif + #ifndef DIV_ROUND_UP #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #endif