mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-28 16:43:09 +00:00
Add support for postponing VirtIO virtqueue interrupts
Partial support for the EVENT_IDX feature was added a while ago, but this commit adds an interface for the device driver to hint how long (in terms of descriptors) the next interrupt should be delayed. The first user of this will be used to reduce VirtIO net's Tx completion interrupts.
This commit is contained in:
parent
e73151eb82
commit
b619f40aec
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=255109
@ -127,7 +127,7 @@ static uint16_t vq_ring_enqueue_segments(struct virtqueue *,
|
||||
static int vq_ring_use_indirect(struct virtqueue *, int);
|
||||
static void vq_ring_enqueue_indirect(struct virtqueue *, void *,
|
||||
struct sglist *, int, int);
|
||||
static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t);
|
||||
static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t);
|
||||
static int vq_ring_must_notify_host(struct virtqueue *);
|
||||
static void vq_ring_notify_host(struct virtqueue *);
|
||||
static void vq_ring_free_chain(struct virtqueue *, uint16_t);
|
||||
@ -440,28 +440,38 @@ virtqueue_enable_intr(struct virtqueue *vq)
|
||||
}
|
||||
|
||||
int
|
||||
virtqueue_postpone_intr(struct virtqueue *vq)
|
||||
virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint)
|
||||
{
|
||||
uint16_t ndesc, avail_idx;
|
||||
|
||||
/*
|
||||
* Request the next interrupt be postponed until at least half
|
||||
* of the available descriptors have been consumed.
|
||||
*/
|
||||
avail_idx = vq->vq_ring.avail->idx;
|
||||
ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx) / 2;
|
||||
ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx);
|
||||
|
||||
switch (hint) {
|
||||
case VQ_POSTPONE_SHORT:
|
||||
ndesc /= 4;
|
||||
break;
|
||||
case VQ_POSTPONE_LONG:
|
||||
ndesc *= 3 / 4;
|
||||
break;
|
||||
case VQ_POSTPONE_EMPTIED:
|
||||
break;
|
||||
}
|
||||
|
||||
return (vq_ring_enable_interrupt(vq, ndesc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Note this is only considered a hint to the host.
|
||||
*/
|
||||
void
|
||||
virtqueue_disable_intr(struct virtqueue *vq)
|
||||
{
|
||||
|
||||
/*
|
||||
* Note this is only considered a hint to the host.
|
||||
*/
|
||||
if ((vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) == 0)
|
||||
if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) {
|
||||
vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx -
|
||||
vq->vq_nentries - 1;
|
||||
} else
|
||||
vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,16 @@ struct sglist;
|
||||
/* Device callback for a virtqueue interrupt. */
|
||||
typedef void virtqueue_intr_t(void *);
|
||||
|
||||
/*
|
||||
* Hint on how long the next interrupt should be postponed. This is
|
||||
* only used when the EVENT_IDX feature is negotiated.
|
||||
*/
|
||||
typedef enum {
|
||||
VQ_POSTPONE_SHORT,
|
||||
VQ_POSTPONE_LONG,
|
||||
VQ_POSTPONE_EMPTIED /* Until all available desc are used. */
|
||||
} vq_postpone_t;
|
||||
|
||||
#define VIRTQUEUE_MAX_NAME_SZ 32
|
||||
|
||||
/* One for each virtqueue the device wishes to allocate. */
|
||||
@ -73,7 +83,7 @@ int virtqueue_reinit(struct virtqueue *vq, uint16_t size);
|
||||
int virtqueue_intr_filter(struct virtqueue *vq);
|
||||
void virtqueue_intr(struct virtqueue *vq);
|
||||
int virtqueue_enable_intr(struct virtqueue *vq);
|
||||
int virtqueue_postpone_intr(struct virtqueue *vq);
|
||||
int virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint);
|
||||
void virtqueue_disable_intr(struct virtqueue *vq);
|
||||
|
||||
/* Get physical address of the virtqueue ring. */
|
||||
|
Loading…
Reference in New Issue
Block a user