shithub: riscv

Download patch

ref: a0bb446d75c2f5f00745503a06d171c6ea02ee9d
parent: 469a10f1d95ef94c00fe1a78466e63be130fed1f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Dec 8 22:23:53 EST 2014

ethervirtio: fix queue notifications and interrupt flags, avoid useless notifications

bug: Rnointerrupt was used on Vqueue.used.flags instead of
Vqueue.avail.flags.

introduce vqnotify() function that notifies the device
about available ring advancement.

avoid queue notifications there that can be slow by
checking Unonotify flag in Vqueue.used.flags.

keep track of the number of notifications in the queue.

--- a/sys/src/9/pc/ethervirtio.c
+++ b/sys/src/9/pc/ethervirtio.c
@@ -137,6 +137,7 @@
 	u16int	lastused;
 
 	uint	nintr;
+	uint	nnote;
 };
 
 struct Ctlr {
@@ -169,6 +170,19 @@
 }
 
 static void
+vqnotify(Ctlr *ctlr, int x)
+{
+	Vqueue *q;
+
+	coherence();
+	q = &ctlr->queue[x];
+	if(q->used->flags & Unonotify)
+		return;
+	q->nnote++;
+	outs(ctlr->port+Qnotify, x);
+}
+
+static void
 txproc(void *v)
 {
 	Vheader *header;
@@ -201,7 +215,7 @@
 		q->desc[j].flags = 0;
 	}
 
-	q->used->flags &= ~Rnointerrupt;
+	q->avail->flags &= ~Rnointerrupt;
 
 	while(waserror())
 		;
@@ -236,7 +250,7 @@
 		q->desc[j].len = BLEN(b);
 		coherence();
 		q->avail->idx++;
-		outs(ctlr->port+Qnotify, Vtxq);
+		vqnotify(ctlr, Vtxq);
 	}
 
 	pexit("ether out queue closed", 1);
@@ -275,7 +289,7 @@
 		q->desc[j].flags = Dwrite;
 	}
 
-	q->used->flags &= ~Rnointerrupt;
+	q->avail->flags &= ~Rnointerrupt;
 
 	while(waserror())
 		;
@@ -294,8 +308,8 @@
 			q->desc[j].len = BALLOC(b);
 			coherence();
 			q->avail->idx++;
-			outs(ctlr->port+Qnotify, Vrxq);
 		} while(q->avail->idx != q->used->idx);
+		vqnotify(ctlr, Vrxq);
 
 		/* wait for any packets to complete */
 		if(!vhasroom(q))
@@ -359,13 +373,13 @@
 	q->availent[i] = 0;
 	coherence();
 
-	q->used->flags &= ~Rnointerrupt;
+	q->avail->flags &= ~Rnointerrupt;
 	q->avail->idx++;
-	outs(ctlr->port+Qnotify, Vctlq);
+	vqnotify(ctlr, Vctlq);
 	while(!vhasroom(q))
 		sleep(q, vhasroom, q);
 	q->lastused = q->used->idx;
-	q->used->flags |= Rnointerrupt;
+	q->avail->flags |= Rnointerrupt;
 
 	qunlock(&ctlr->ctllock);
 	poperror();
@@ -440,8 +454,9 @@
 
 	for(i = 0; i < ctlr->nqueue; i++){
 		q = &ctlr->queue[i];
-		l += snprint(p+l, READSTR-l, "vq%d %#p size %d avail->idx %d used->idx %d lastused %hud nintr %ud\n",
-			i, q, q->qsize, q->avail->idx, q->used->idx, q->lastused, q->nintr);
+		l += snprint(p+l, READSTR-l,
+			"vq%d %#p size %d avail->idx %d used->idx %d lastused %hud nintr %ud nnote %ud\n",
+			i, q, q->qsize, q->avail->idx, q->used->idx, q->lastused, q->nintr, q->nnote);
 	}
 
 	n = readstr(offset, a, n, p);
@@ -520,7 +535,8 @@
 	q->qmask = q->qsize - 1;
 
 	q->lastused = q->avail->idx = q->used->idx = 0;
-	q->used->flags |= Rnointerrupt;
+
+	q->avail->flags |= Rnointerrupt;
 
 	return 0;
 }