mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
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:
parent
df075012e8
commit
f3464815ee
4 changed files with 47 additions and 32 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue