usb: fix isowrite putsamples race
This commit is contained in:
parent
1be10947ba
commit
cfd25faa28
3 changed files with 51 additions and 42 deletions
|
@ -1762,25 +1762,23 @@ epctlio(Ep *ep, Ctlio *cio, void *a, long count)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put new samples in the dummy Td.
|
* Put new samples in the dummy Td.
|
||||||
* BUG: This does only a transfer per Td. We could do up to 8.
|
|
||||||
*/
|
*/
|
||||||
static long
|
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;
|
Td *td;
|
||||||
ulong n;
|
|
||||||
|
|
||||||
td = pa2ptr(iso->ed->tail);
|
td = pa2ptr(iso->ed->tail);
|
||||||
n = count;
|
|
||||||
if(n > td->nbytes - BLEN(td->bp))
|
if(n > td->nbytes - BLEN(td->bp))
|
||||||
n = td->nbytes - BLEN(td->bp);
|
n = td->nbytes - BLEN(td->bp);
|
||||||
assert(td->bp->wp + n <= td->bp->lim);
|
assert(td->bp->wp + n <= td->bp->lim);
|
||||||
|
iunlock(ctlr); /* We could page fault here */
|
||||||
memmove(td->bp->wp, b, n);
|
memmove(td->bp->wp, b, n);
|
||||||
td->bp->wp += n;
|
ilock(ctlr);
|
||||||
if(BLEN(td->bp) == td->nbytes){ /* full Td: activate it */
|
if(td == pa2ptr(iso->ed->tail)){
|
||||||
ilock(ctlr);
|
td->bp->wp += n;
|
||||||
isoadvance(ep, iso, td);
|
if(BLEN(td->bp) == td->nbytes) /* full Td: activate it */
|
||||||
iunlock(ctlr);
|
isoadvance(ep, iso, td);
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -1834,9 +1832,7 @@ episowrite(Ep *ep, void *a, long count)
|
||||||
}
|
}
|
||||||
if(iso->state != Qrun)
|
if(iso->state != Qrun)
|
||||||
panic("episowrite: iso not running");
|
panic("episowrite: iso not running");
|
||||||
iunlock(ctlr); /* We could page fault here */
|
|
||||||
nw = putsamples(ctlr, ep, iso, b+tot, count-tot);
|
nw = putsamples(ctlr, ep, iso, b+tot, count-tot);
|
||||||
ilock(ctlr);
|
|
||||||
}
|
}
|
||||||
while(isodelay(iso) == 0){
|
while(isodelay(iso) == 0){
|
||||||
iunlock(ctlr);
|
iunlock(ctlr);
|
||||||
|
|
|
@ -993,21 +993,27 @@ interrupt(Ureg*, void *a)
|
||||||
* it is activated and tdu advanced.
|
* it is activated and tdu advanced.
|
||||||
*/
|
*/
|
||||||
static long
|
static long
|
||||||
putsamples(Isoio *iso, uchar *b, long count)
|
putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count)
|
||||||
{
|
{
|
||||||
long tot;
|
long n, tot, left;
|
||||||
long n;
|
Td *tdu;
|
||||||
|
|
||||||
for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
|
for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
|
||||||
n = count-tot;
|
n = count-tot;
|
||||||
if(n > maxtdlen(iso->tdu) - iso->nleft)
|
tdu = iso->tdu;
|
||||||
n = maxtdlen(iso->tdu) - iso->nleft;
|
left = iso->nleft;
|
||||||
memmove(iso->tdu->data+iso->nleft, b+tot, n);
|
if(n > maxtdlen(tdu) - left)
|
||||||
|
n = maxtdlen(tdu) - left;
|
||||||
|
iunlock(ctlr); /* can pagefault here */
|
||||||
|
memmove(tdu->data+left, b+tot, n);
|
||||||
|
ilock(ctlr);
|
||||||
|
if(tdu != iso->tdu)
|
||||||
|
continue;
|
||||||
iso->nleft += n;
|
iso->nleft += n;
|
||||||
if(iso->nleft == maxtdlen(iso->tdu)){
|
if(iso->nleft == maxtdlen(tdu)){
|
||||||
tdisoinit(iso, iso->tdu, iso->nleft);
|
tdisoinit(iso, tdu, iso->nleft);
|
||||||
|
iso->tdu = tdu->next;
|
||||||
iso->nleft = 0;
|
iso->nleft = 0;
|
||||||
iso->tdu = iso->tdu->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tot;
|
return tot;
|
||||||
|
@ -1065,9 +1071,7 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count)
|
||||||
}
|
}
|
||||||
if(iso->state != Qrun)
|
if(iso->state != Qrun)
|
||||||
panic("episowrite: iso not running");
|
panic("episowrite: iso not running");
|
||||||
iunlock(ctlr); /* We could page fault here */
|
nw = putsamples(ctlr, iso, b+tot, count-tot);
|
||||||
nw = putsamples(iso, b+tot, count-tot);
|
|
||||||
ilock(ctlr);
|
|
||||||
}
|
}
|
||||||
while(isodelay(iso) == 0){
|
while(isodelay(iso) == 0){
|
||||||
iunlock(ctlr);
|
iunlock(ctlr);
|
||||||
|
|
|
@ -1996,33 +1996,44 @@ episoread(Ep *ep, Isoio *iso, void *a, long count)
|
||||||
* it is activated and tdu advanced.
|
* it is activated and tdu advanced.
|
||||||
*/
|
*/
|
||||||
static long
|
static long
|
||||||
putsamples(Isoio *iso, uchar *b, long count)
|
putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count)
|
||||||
{
|
{
|
||||||
long tot, n;
|
long left, tot, n;
|
||||||
|
Sitd *stdu;
|
||||||
|
Itd *tdu;
|
||||||
|
|
||||||
for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
|
for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
|
||||||
n = count-tot;
|
n = count-tot;
|
||||||
|
left = iso->nleft;
|
||||||
if(iso->hs != 0){
|
if(iso->hs != 0){
|
||||||
if(n > iso->tdu->mdata - iso->nleft)
|
tdu = iso->tdu;
|
||||||
n = iso->tdu->mdata - iso->nleft;
|
if(n > tdu->mdata - left)
|
||||||
memmove(iso->tdu->data + iso->nleft, b + tot, n);
|
n = tdu->mdata - left;
|
||||||
coherence();
|
iunlock(ctlr); /* We could page fault here */
|
||||||
|
memmove(tdu->data + left, b + tot, n);
|
||||||
|
ilock(ctlr);
|
||||||
|
if(iso->tdu != tdu)
|
||||||
|
continue;
|
||||||
iso->nleft += n;
|
iso->nleft += n;
|
||||||
if(iso->nleft == iso->tdu->mdata){
|
if(iso->nleft == tdu->mdata){
|
||||||
itdinit(iso, iso->tdu);
|
itdinit(iso, tdu);
|
||||||
|
iso->tdu = tdu->next;
|
||||||
iso->nleft = 0;
|
iso->nleft = 0;
|
||||||
iso->tdu = iso->tdu->next;
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(n > iso->stdu->mdata - iso->nleft)
|
stdu = iso->stdu;
|
||||||
n = iso->stdu->mdata - iso->nleft;
|
if(n > stdu->mdata - left)
|
||||||
memmove(iso->stdu->data + iso->nleft, b + tot, n);
|
n = stdu->mdata - left;
|
||||||
coherence();
|
iunlock(ctlr); /* We could page fault here */
|
||||||
|
memmove(stdu->data + left, b + tot, n);
|
||||||
|
ilock(ctlr);
|
||||||
|
if(iso->stdu != stdu)
|
||||||
|
continue;
|
||||||
iso->nleft += n;
|
iso->nleft += n;
|
||||||
if(iso->nleft == iso->stdu->mdata){
|
if(iso->nleft == stdu->mdata){
|
||||||
sitdinit(iso, iso->stdu);
|
sitdinit(iso, stdu);
|
||||||
|
iso->stdu = stdu->next;
|
||||||
iso->nleft = 0;
|
iso->nleft = 0;
|
||||||
iso->stdu = iso->stdu->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2081,9 +2092,7 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count)
|
||||||
}
|
}
|
||||||
if(iso->state != Qrun)
|
if(iso->state != Qrun)
|
||||||
panic("episowrite: iso not running");
|
panic("episowrite: iso not running");
|
||||||
iunlock(ctlr); /* We could page fault here */
|
nw = putsamples(ctlr, iso, b+tot, count-tot);
|
||||||
nw = putsamples(iso, b+tot, count-tot);
|
|
||||||
ilock(ctlr);
|
|
||||||
}
|
}
|
||||||
while(isodelay(iso) == 0){
|
while(isodelay(iso) == 0){
|
||||||
iunlock(ctlr);
|
iunlock(ctlr);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue