summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/usbohci.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-09-03 01:54:34 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-09-03 01:54:34 +0200
commitcfd25faa2857ee9de75910d81530be62d7ba4704 (patch)
tree1bebf05a269d6923290e5e362a5bdf46fda6e8f4 /sys/src/9/pc/usbohci.c
parent1be10947ba37964feb10e0cf45576b029043866b (diff)
usb: fix isowrite putsamples race
Diffstat (limited to 'sys/src/9/pc/usbohci.c')
-rw-r--r--sys/src/9/pc/usbohci.c18
1 files changed, 7 insertions, 11 deletions
diff --git a/sys/src/9/pc/usbohci.c b/sys/src/9/pc/usbohci.c
index 1b9c3cf0c..154da3062 100644
--- a/sys/src/9/pc/usbohci.c
+++ b/sys/src/9/pc/usbohci.c
@@ -1762,25 +1762,23 @@ epctlio(Ep *ep, Ctlio *cio, void *a, long count)
/*
* Put new samples in the dummy Td.
- * BUG: This does only a transfer per Td. We could do up to 8.
*/
static long
-putsamples(Ctlr *ctlr, Ep *ep, Isoio *iso, uchar *b, long count)
+putsamples(Ctlr *ctlr, Ep *ep, Isoio *iso, uchar *b, long n)
{
Td *td;
- ulong n;
td = pa2ptr(iso->ed->tail);
- n = count;
if(n > td->nbytes - BLEN(td->bp))
n = td->nbytes - BLEN(td->bp);
assert(td->bp->wp + n <= td->bp->lim);
+ iunlock(ctlr); /* We could page fault here */
memmove(td->bp->wp, b, n);
- td->bp->wp += n;
- if(BLEN(td->bp) == td->nbytes){ /* full Td: activate it */
- ilock(ctlr);
- isoadvance(ep, iso, td);
- iunlock(ctlr);
+ ilock(ctlr);
+ if(td == pa2ptr(iso->ed->tail)){
+ td->bp->wp += n;
+ if(BLEN(td->bp) == td->nbytes) /* full Td: activate it */
+ isoadvance(ep, iso, td);
}
return n;
}
@@ -1834,9 +1832,7 @@ episowrite(Ep *ep, void *a, long count)
}
if(iso->state != Qrun)
panic("episowrite: iso not running");
- iunlock(ctlr); /* We could page fault here */
nw = putsamples(ctlr, ep, iso, b+tot, count-tot);
- ilock(ctlr);
}
while(isodelay(iso) == 0){
iunlock(ctlr);