diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-07-02 10:47:35 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-07-27 08:25:27 +0200 |
commit | 64f64855d0ec2c5979f6986d2f52e8861d58e208 (patch) | |
tree | 02defb63ea385ea4cac472fa68e04177b80e98ca /hw | |
parent | b6866fee58bc25b01485dcfcf8be44a915c5f573 (diff) |
virtio-scsi: Report missed events
When an event is reported but no buffers are present in the event vq,
we can set a flag and report a dummy event as soon as one is added.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/virtio-scsi.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 4f021957f7..d5c5984e08 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -141,6 +141,7 @@ typedef struct { uint32_t sense_size; uint32_t cdb_size; int resetting; + bool events_dropped; VirtQueue *ctrl_vq; VirtQueue *event_vq; VirtQueue *cmd_vqs[0]; @@ -416,10 +417,6 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) } } -static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq) -{ -} - static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, size_t resid) { @@ -594,22 +591,34 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, { VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq); VirtIOSCSIEvent *evt; + int in_size; - if (req) { - int in_size; - if (req->elem.out_num || req->elem.in_num != 1) { - virtio_scsi_bad_req(); - } + if (!req) { + s->events_dropped = true; + return; + } - in_size = req->elem.in_sg[0].iov_len; - if (in_size < sizeof(VirtIOSCSIEvent)) { - virtio_scsi_bad_req(); - } + if (req->elem.out_num || req->elem.in_num != 1) { + virtio_scsi_bad_req(); + } - evt = req->resp.event; - memset(evt, 0, sizeof(VirtIOSCSIEvent)); - evt->event = event; - evt->reason = reason; + if (s->events_dropped) { + event |= VIRTIO_SCSI_T_EVENTS_MISSED; + s->events_dropped = false; + } + + in_size = req->elem.in_sg[0].iov_len; + if (in_size < sizeof(VirtIOSCSIEvent)) { + virtio_scsi_bad_req(); + } + + evt = req->resp.event; + memset(evt, 0, sizeof(VirtIOSCSIEvent)); + evt->event = event; + evt->reason = reason; + if (!dev) { + assert(event == VIRTIO_SCSI_T_NO_EVENT); + } else { evt->lun[0] = 1; evt->lun[1] = dev->id; @@ -618,7 +627,16 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, evt->lun[2] = (dev->lun >> 8) | 0x40; } evt->lun[3] = dev->lun & 0xFF; - virtio_scsi_complete_req(req); + } + virtio_scsi_complete_req(req); +} + +static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOSCSI *s = (VirtIOSCSI *)vdev; + + if (s->events_dropped) { + virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0); } } |