in vringh.c [481:526]
static inline int __vringh_need_notify(struct vringh *vrh,
int (*getu16)(const struct vringh *vrh,
u16 *val,
const __virtio16 *p))
{
bool notify;
u16 used_event;
int err;
/* Flush out used index update. This is paired with the
* barrier that the Guest executes when enabling
* interrupts. */
virtio_mb(vrh->weak_barriers);
/* Old-style, without event indices. */
if (!vrh->event_indices) {
u16 flags;
err = getu16(vrh, &flags, &vrh->vring.avail->flags);
if (err) {
vringh_bad("Failed to get flags at %p",
&vrh->vring.avail->flags);
return err;
}
return (!(flags & VRING_AVAIL_F_NO_INTERRUPT));
}
/* Modern: we know when other side wants to know. */
err = getu16(vrh, &used_event, &vring_used_event(&vrh->vring));
if (err) {
vringh_bad("Failed to get used event idx at %p",
&vring_used_event(&vrh->vring));
return err;
}
/* Just in case we added so many that we wrap. */
if (unlikely(vrh->completed > 0xffff))
notify = true;
else
notify = vring_need_event(used_event,
vrh->last_used_idx + vrh->completed,
vrh->last_used_idx);
vrh->last_used_idx += vrh->completed;
vrh->completed = 0;
return notify;
}