Index: sys/dev/virtio/virtqueue.h =================================================================== --- sys/dev/virtio/virtqueue.h +++ sys/dev/virtio/virtqueue.h @@ -98,6 +98,8 @@ int virtqueue_enqueue(struct virtqueue *vq, void *cookie, struct sglist *sg, int readable, int writable); void *virtqueue_dequeue(struct virtqueue *vq, uint32_t *len); +void *virtqueue_poll_timeout(struct virtqueue *vq, uint32_t *len, + sbintime_t sbt); void *virtqueue_poll(struct virtqueue *vq, uint32_t *len); #endif /* _VIRTIO_VIRTQUEUE_H */ Index: sys/dev/virtio/virtqueue.c =================================================================== --- sys/dev/virtio/virtqueue.c +++ sys/dev/virtio/virtqueue.c @@ -604,12 +604,15 @@ } void * -virtqueue_poll(struct virtqueue *vq, uint32_t *len) +virtqueue_poll_timeout(struct virtqueue *vq, uint32_t *len, sbintime_t sbt) { void *cookie; + sbintime_t timeout_at; + timeout_at = sbt == 0 ? 0 : getsbinuptime() + sbt; VIRTIO_BUS_POLL(vq->vq_dev); - while ((cookie = virtqueue_dequeue(vq, len)) == NULL) { + while ((cookie = virtqueue_dequeue(vq, len)) == NULL && + (timeout_at == 0 || getsbinuptime() < timeout_at)) { cpu_spinwait(); VIRTIO_BUS_POLL(vq->vq_dev); } @@ -617,6 +620,17 @@ return (cookie); } +void * +virtqueue_poll(struct virtqueue *vq, uint32_t *len) +{ + void *cookie; + + cookie = virtqueue_poll_timeout(vq, len, 0); + /* No reason for this to have failed. */ + MPASS(cookie != NULL); + return (cookie); +} + void * virtqueue_drain(struct virtqueue *vq, int *last) {