/** * * vq_ring_enable_interrupt * */ static int vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) { /* * Enable interrupts, making sure we get the latest index of * what's already been consumed. */ if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; } else { vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; } env_mb(); /* * Enough items may have already been consumed to meet our threshold * since we last checked. Let our caller know so it processes the new * entries. */ if (virtqueue_nused(vq) > ndesc) { return (1); } return (0); }
int virtqueue_postpone_intr(struct virtqueue *vq) { uint16_t ndesc; /* * Postpone until at least half of the available descriptors * have been consumed. * * XXX Adaptive factor? (Linux uses 3/4) */ ndesc = (uint16_t)(vq->vq_ring.avail->idx - vq->vq_used_cons_idx) / 2; if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; else vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; cpu_mfence(); /* * Enough items may have already been consumed to meet our * threshold since we last checked. Let our caller know so * it processes the new entries. */ if (virtqueue_nused(vq) > ndesc) return (1); return (0); }
/** * virtqueue_dump Dumps important virtqueue fields , use for debugging purposes * * @param vq - Pointer to VirtIO queue control block */ void virtqueue_dump(struct virtqueue *vq) { if (vq == VQ_NULL) return; env_print("VQ: %s - size=%d; free=%d; used=%d; queued=%d; " "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; " "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", vq->vq_name, vq->vq_nentries, vq->vq_free_cnt, virtqueue_nused(vq), vq->vq_queued_cnt, vq->vq_desc_head_idx, vq->vq_ring.avail->idx, vq->vq_used_cons_idx, vq->vq_ring.used->idx, vq->vq_ring.avail->flags, vq->vq_ring.used->flags); }