diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 00:14:43 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 00:14:43 -0500 |
commit | e93300b1afc7cd4fe1e741ceaf06714d060e88b8 (patch) | |
tree | 060bb46e8d7b570fa08df94aef1cf4cc3620f8c5 | |
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>
-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 36bb6a613728..79e1b292c030 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/hrtimer.h> | ||
25 | 26 | ||
26 | /* virtio guest is communicating with a virtual "device" that actually runs on | 27 | /* virtio guest is communicating with a virtual "device" that actually runs on |
27 | * a host processor. Memory barriers are used to control SMP effects. */ | 28 | * a host processor. Memory barriers are used to control SMP effects. */ |
@@ -108,6 +109,10 @@ struct vring_virtqueue | |||
108 | #ifdef DEBUG | 109 | #ifdef DEBUG |
109 | /* They're supposed to lock for us. */ | 110 | /* They're supposed to lock for us. */ |
110 | unsigned int in_use; | 111 | unsigned int in_use; |
112 | |||
113 | /* Figure out if their kicks are too delayed. */ | ||
114 | bool last_add_time_valid; | ||
115 | ktime_t last_add_time; | ||
111 | #endif | 116 | #endif |
112 | 117 | ||
113 | /* Tokens for callbacks. */ | 118 | /* Tokens for callbacks. */ |
@@ -198,6 +203,19 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
198 | 203 | ||
199 | BUG_ON(data == NULL); | 204 | BUG_ON(data == NULL); |
200 | 205 | ||
206 | #ifdef DEBUG | ||
207 | { | ||
208 | ktime_t now = ktime_get(); | ||
209 | |||
210 | /* No kick or get, with .1 second between? Warn. */ | ||
211 | if (vq->last_add_time_valid) | ||
212 | WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time)) | ||
213 | > 100); | ||
214 | vq->last_add_time = now; | ||
215 | vq->last_add_time_valid = true; | ||
216 | } | ||
217 | #endif | ||
218 | |||
201 | /* If the host supports indirect descriptor tables, and we have multiple | 219 | /* If the host supports indirect descriptor tables, and we have multiple |
202 | * buffers, then go indirect. FIXME: tune this threshold */ | 220 | * buffers, then go indirect. FIXME: tune this threshold */ |
203 | if (vq->indirect && (out + in) > 1 && vq->num_free) { | 221 | if (vq->indirect && (out + in) > 1 && vq->num_free) { |
@@ -298,6 +316,14 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq) | |||
298 | new = vq->vring.avail->idx; | 316 | new = vq->vring.avail->idx; |
299 | vq->num_added = 0; | 317 | vq->num_added = 0; |
300 | 318 | ||
319 | #ifdef DEBUG | ||
320 | if (vq->last_add_time_valid) { | ||
321 | WARN_ON(ktime_to_ms(ktime_sub(ktime_get(), | ||
322 | vq->last_add_time)) > 100); | ||
323 | } | ||
324 | vq->last_add_time_valid = false; | ||
325 | #endif | ||
326 | |||
301 | if (vq->event) { | 327 | if (vq->event) { |
302 | needs_kick = vring_need_event(vring_avail_event(&vq->vring), | 328 | needs_kick = vring_need_event(vring_avail_event(&vq->vring), |
303 | new, old); | 329 | new, old); |
@@ -435,6 +461,10 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | |||
435 | virtio_mb(vq); | 461 | virtio_mb(vq); |
436 | } | 462 | } |
437 | 463 | ||
464 | #ifdef DEBUG | ||
465 | vq->last_add_time_valid = false; | ||
466 | #endif | ||
467 | |||
438 | END_USE(vq); | 468 | END_USE(vq); |
439 | return ret; | 469 | return ret; |
440 | } | 470 | } |
@@ -620,6 +650,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, | |||
620 | list_add_tail(&vq->vq.list, &vdev->vqs); | 650 | list_add_tail(&vq->vq.list, &vdev->vqs); |
621 | #ifdef DEBUG | 651 | #ifdef DEBUG |
622 | vq->in_use = false; | 652 | vq->in_use = false; |
653 | vq->last_add_time_valid = false; | ||
623 | #endif | 654 | #endif |
624 | 655 | ||
625 | vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); | 656 | vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); |