MFp4 //depot/projects/usb@159673

Fix a corner case around stalling SETUP packets in device side mode.

Submitted by:	Hans Petter Selasky
This commit is contained in:
Andrew Thompson 2009-04-05 18:18:16 +00:00
parent df075012e8
commit f3464815ee
4 changed files with 47 additions and 32 deletions

View file

@ -305,14 +305,11 @@ at91dci_setup_rx(struct at91dci_td *td)
AT91_UDP_CSR_TXCOMP);
if (!(csr & AT91_UDP_CSR_RXSETUP)) {
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
temp |= AT91_UDP_CSR_FORCESTALL;
td->did_stall = 1;
}
goto not_complete;
}
/* clear did stall */
td->did_stall = 0;
/* get the packet byte count */
count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16;
@ -362,6 +359,13 @@ at91dci_setup_rx(struct at91dci_td *td)
return (0); /* complete */
not_complete:
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
temp |= AT91_UDP_CSR_FORCESTALL;
td->did_stall = 1;
}
/* clear interrupts, if any */
if (temp) {
DPRINTFN(5, "clearing 0x%08x\n", temp);

View file

@ -250,16 +250,10 @@ atmegadci_setup_rx(struct atmegadci_td *td)
DPRINTFN(5, "UEINTX=0x%02x\n", temp);
if (!(temp & ATMEGA_UEINTX_RXSTPI)) {
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
ATMEGA_UECONX_EPEN |
ATMEGA_UECONX_STALLRQ);
td->did_stall = 1;
}
goto not_complete;
}
/* clear did stall */
td->did_stall = 0;
/* get the packet byte count */
count =
(ATMEGA_READ_1(sc, ATMEGA_UEBCHX) << 8) |
@ -304,6 +298,15 @@ atmegadci_setup_rx(struct atmegadci_td *td)
return (0); /* complete */
not_complete:
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
ATMEGA_UECONX_EPEN |
ATMEGA_UECONX_STALLRQ);
td->did_stall = 1;
}
/* we only want to know if there is a SETUP packet */
ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, ATMEGA_UEIENX_RXSTPE);
return (1); /* not complete */

View file

@ -255,6 +255,8 @@ musbotg_setup_rx(struct musbotg_td *td)
* callback, hence the status stage is not complete.
*/
if (csr & MUSB2_MASK_CSR0L_DATAEND) {
/* do not stall at this point */
td->did_stall = 1;
/* wait for interrupt */
goto not_complete;
}
@ -276,18 +278,13 @@ musbotg_setup_rx(struct musbotg_td *td)
sc->sc_ep0_busy = 0;
}
if (sc->sc_ep0_busy) {
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(4, "stalling\n");
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
MUSB2_MASK_CSR0L_SENDSTALL);
td->did_stall = 1;
}
goto not_complete;
}
if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
goto not_complete;
}
/* clear did stall flag */
td->did_stall = 0;
/* get the packet byte count */
count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
@ -328,6 +325,13 @@ musbotg_setup_rx(struct musbotg_td *td)
return (0); /* complete */
not_complete:
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(4, "stalling\n");
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
MUSB2_MASK_CSR0L_SENDSTALL);
td->did_stall = 1;
}
return (1); /* not complete */
}

View file

@ -248,19 +248,11 @@ uss820dci_setup_rx(struct uss820dci_td *td)
DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
if (!(rx_stat & USS820_RXSTAT_RXSETUP)) {
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
/* set stall */
uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
(USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
td->did_stall = 1;
}
goto not_complete;
}
/* clear did stall */
td->did_stall = 0;
/* clear stall and all I/O */
uss820dci_update_shared_1(sc, USS820_EPCON,
0xFF ^ (USS820_EPCON_TXSTL |
@ -332,6 +324,18 @@ uss820dci_setup_rx(struct uss820dci_td *td)
return (0); /* complete */
not_complete:
/* abort any ongoing transfer */
if (!td->did_stall) {
DPRINTFN(5, "stalling\n");
/* set stall */
uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
(USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
td->did_stall = 1;
}
/* clear end overwrite flag, if any */
if (rx_stat & USS820_RXSTAT_RXSETUP) {
uss820dci_update_shared_1(sc, USS820_RXSTAT,