diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-12-07 15:34:53 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-12-07 15:34:53 +0100 |
commit | aff0dc5e673bcf905ebbde0094b2611dd57b5bed (patch) | |
tree | f48892309cbfa96f7ab315cec80b7b7cbec493cb /sys/src/9/pc/ethervirtio.c | |
parent | 964dafbdf0f47f798f9beda4b656625506acbedf (diff) |
ethervirtio: avoid dumping packets in txproc when ring gets full
Diffstat (limited to 'sys/src/9/pc/ethervirtio.c')
-rw-r--r-- | sys/src/9/pc/ethervirtio.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/sys/src/9/pc/ethervirtio.c b/sys/src/9/pc/ethervirtio.c index 3e339d5ef..07207453d 100644 --- a/sys/src/9/pc/ethervirtio.c +++ b/sys/src/9/pc/ethervirtio.c @@ -197,33 +197,36 @@ txproc(void *v) 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); |