diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 15:44:43 +1030 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 15:44:43 +1030 |
commit | e93300b1afc7cd4fe1e741ceaf06714d060e88b8 (patch) | |
tree | 060bb46e8d7b570fa08df94aef1cf4cc3620f8c5 /drivers/virtio | |
parent | ee7cd8981e15bcb365fc762afe3fc47b8242f630 (diff) |
virtio: add debugging if driver doesn't kick.
Under the existing #ifdef DEBUG, check that they don't have more than
1/10 of a second between an add_buf() and a
virtqueue_notify()/virtqueue_kick_prepare() call.
We could get false positives on a really busy system, but good for
development.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio')
-rw-r--r-- | drivers/virtio/virtio_ring.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 36bb6a61372..79e1b292c03 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -22,6 +22,7 @@ #include <linux/device.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/hrtimer.h> /* virtio guest is communicating with a virtual "device" that actually runs on * a host processor. Memory barriers are used to control SMP effects. */ @@ -108,6 +109,10 @@ struct vring_virtqueue #ifdef DEBUG /* They're supposed to lock for us. */ unsigned int in_use; + + /* Figure out if their kicks are too delayed. */ + bool last_add_time_valid; + ktime_t last_add_time; #endif /* Tokens for callbacks. */ @@ -198,6 +203,19 @@ int virtqueue_add_buf(struct virtqueue *_vq, BUG_ON(data == NULL); +#ifdef DEBUG + { + ktime_t now = ktime_get(); + + /* No kick or get, with .1 second between? Warn. */ + if (vq->last_add_time_valid) + WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time)) + > 100); + vq->last_add_time = now; + vq->last_add_time_valid = true; + } +#endif + /* If the host supports indirect descriptor tables, and we have multiple * buffers, then go indirect. FIXME: tune this threshold */ if (vq->indirect && (out + in) > 1 && vq->num_free) { @@ -298,6 +316,14 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq) new = vq->vring.avail->idx; vq->num_added = 0; +#ifdef DEBUG + if (vq->last_add_time_valid) { + WARN_ON(ktime_to_ms(ktime_sub(ktime_get(), + vq->last_add_time)) > 100); + } + vq->last_add_time_valid = false; +#endif + if (vq->event) { needs_kick = vring_need_event(vring_avail_event(&vq->vring), new, old); @@ -435,6 +461,10 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) virtio_mb(vq); } +#ifdef DEBUG + vq->last_add_time_valid = false; +#endif + END_USE(vq); return ret; } @@ -620,6 +650,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, list_add_tail(&vq->vq.list, &vdev->vqs); #ifdef DEBUG vq->in_use = false; + vq->last_add_time_valid = false; #endif vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); |