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>
This commit is contained in:
Родитель
ee7cd8981e
Коммит
e93300b1af
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/hrtimer.h>
|
||||||
|
|
||||||
/* virtio guest is communicating with a virtual "device" that actually runs on
|
/* virtio guest is communicating with a virtual "device" that actually runs on
|
||||||
* a host processor. Memory barriers are used to control SMP effects. */
|
* a host processor. Memory barriers are used to control SMP effects. */
|
||||||
|
@ -108,6 +109,10 @@ struct vring_virtqueue
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* They're supposed to lock for us. */
|
/* They're supposed to lock for us. */
|
||||||
unsigned int in_use;
|
unsigned int in_use;
|
||||||
|
|
||||||
|
/* Figure out if their kicks are too delayed. */
|
||||||
|
bool last_add_time_valid;
|
||||||
|
ktime_t last_add_time;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tokens for callbacks. */
|
/* Tokens for callbacks. */
|
||||||
|
@ -198,6 +203,19 @@ int virtqueue_add_buf(struct virtqueue *_vq,
|
||||||
|
|
||||||
BUG_ON(data == NULL);
|
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
|
/* If the host supports indirect descriptor tables, and we have multiple
|
||||||
* buffers, then go indirect. FIXME: tune this threshold */
|
* buffers, then go indirect. FIXME: tune this threshold */
|
||||||
if (vq->indirect && (out + in) > 1 && vq->num_free) {
|
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;
|
new = vq->vring.avail->idx;
|
||||||
vq->num_added = 0;
|
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) {
|
if (vq->event) {
|
||||||
needs_kick = vring_need_event(vring_avail_event(&vq->vring),
|
needs_kick = vring_need_event(vring_avail_event(&vq->vring),
|
||||||
new, old);
|
new, old);
|
||||||
|
@ -435,6 +461,10 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
|
||||||
virtio_mb(vq);
|
virtio_mb(vq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
vq->last_add_time_valid = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
END_USE(vq);
|
END_USE(vq);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -620,6 +650,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
|
||||||
list_add_tail(&vq->vq.list, &vdev->vqs);
|
list_add_tail(&vq->vq.list, &vdev->vqs);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
vq->in_use = false;
|
vq->in_use = false;
|
||||||
|
vq->last_add_time_valid = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC);
|
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче