aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/input/virtio-input.c29
-rw-r--r--include/hw/virtio/virtio-input.h5
2 files changed, 18 insertions, 16 deletions
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index 728832aa62..0e42f0d02c 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -22,7 +22,6 @@
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
{
VirtQueueElement *elem;
- unsigned have, need;
int i, len;
if (!vinput->active) {
@@ -33,9 +32,9 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
if (vinput->qindex == vinput->qsize) {
vinput->qsize++;
vinput->queue = g_realloc(vinput->queue, vinput->qsize *
- sizeof(virtio_input_event));
+ sizeof(vinput->queue[0]));
}
- vinput->queue[vinput->qindex++] = *event;
+ vinput->queue[vinput->qindex++].event = *event;
/* ... until we see a report sync ... */
if (event->type != cpu_to_le16(EV_SYN) ||
@@ -44,24 +43,24 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
}
/* ... then check available space ... */
- need = sizeof(virtio_input_event) * vinput->qindex;
- virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
- if (have < need) {
- vinput->qindex = 0;
- trace_virtio_input_queue_full();
- return;
- }
-
- /* ... and finally pass them to the guest */
for (i = 0; i < vinput->qindex; i++) {
elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement));
if (!elem) {
- /* should not happen, we've checked for space beforehand */
- fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__);
+ while (--i >= 0) {
+ virtqueue_unpop(vinput->evt, vinput->queue[i].elem, 0);
+ }
+ vinput->qindex = 0;
+ trace_virtio_input_queue_full();
return;
}
+ vinput->queue[i].elem = elem;
+ }
+
+ /* ... and finally pass them to the guest */
+ for (i = 0; i < vinput->qindex; i++) {
+ elem = vinput->queue[i].elem;
len = iov_from_buf(elem->in_sg, elem->in_num,
- 0, vinput->queue+i, sizeof(virtio_input_event));
+ 0, &vinput->queue[i].event, sizeof(virtio_input_event));
virtqueue_push(vinput->evt, elem, len);
g_free(elem);
}
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 55db31087a..91df57eca4 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -62,7 +62,10 @@ struct VirtIOInput {
VirtQueue *evt, *sts;
char *serial;
- virtio_input_event *queue;
+ struct {
+ virtio_input_event event;
+ VirtQueueElement *elem;
+ } *queue;
uint32_t qindex, qsize;
bool active;