ref: aff0dc5e673bcf905ebbde0094b2611dd57b5bed
parent: 964dafbdf0f47f798f9beda4b656625506acbedf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 7 10:34:53 EST 2014
ethervirtio: avoid dumping packets in txproc when ring gets full
--- a/sys/src/9/pc/ethervirtio.c
+++ b/sys/src/9/pc/ethervirtio.c
@@ -197,33 +197,36 @@
q->used->flags &= ~Rnointerrupt;
while((b = qbread(edev->oq, 1000000)) != nil){
- i = q->avail->idx & (q->qmask >> 1);
- if(q->block[i] == nil) {
- /* slot free, fill in descriptor */
- q->block[i] = b;
- j = (i << 1) | 1;
- q->desc[j].addr = PADDR(b->rp);
- q->desc[j].len = BLEN(b);
- coherence();
- q->avail->idx++;
- outs(ctlr->port+Qnotify, Vtxq);
- } else {
- /* transmit ring is full */
- freeb(b);
+ for(;;){
+ /* retire completed packets */
+ while((i = q->lastused) != q->used->idx){
+ u = &q->usedent[i & q->qmask];
+ i = (u->id & q->qmask) >> 1;
+ if(q->block[i] == nil)
+ break;
+ freeb(q->block[i]);
+ q->block[i] = nil;
+ q->lastused++;
+ }
+
+ /* have free slot? */
+ i = q->avail->idx & (q->qmask >> 1);
+ if(q->block[i] == nil)
+ break;
+
+ /* ring full, wait and retry */
if(!vhasroom(q))
sleep(q, vhasroom, q);
}
- /* free completed packets */
- while((i = q->lastused) != q->used->idx){
- u = &q->usedent[i & q->qmask];
- i = (u->id & q->qmask) >> 1;
- if((b = q->block[i]) == nil)
- break;
- q->block[i] = nil;
- freeb(b);
- q->lastused++;
- }
+ /* slot is free, fill in descriptor */
+ q->block[i] = b;
+ j = (i << 1) | 1;
+ q->desc[j].addr = PADDR(b->rp);
+ q->desc[j].len = BLEN(b);
+ coherence();
+ q->avail->idx++;
+ outs(ctlr->port+Qnotify, Vtxq);
}
pexit("ether out queue closed", 1);