On Fri, 5 Feb 2021 20:12:04 +0100 Pali Rohár <p...@kernel.org> wrote:
> If musb_peri_rx_ep() was called to processed received HW buffer but > U-Boot cannot read it yet (e.g. because U-Boot SW buffer is full) > then interrupt was marked as processed but HW buffer stayed > unprocessed. > > U-Boot tried to process this buffer again when it receive interrupt > again, but it can receive it only when sender (host) send a new data. > As sender (host) is not going to send a new data until U-Boot process > current data this issue caused a deadlock in case sender (host) is > emitting data faster than U-Boot can process it. > > Reading musb intrrx register automatically clears this register and > mark interrupt as processed. So to prevent marking interrupt in > U-Boot as processed and a new variable pending_intrrx which would > contain unprocessed bits of intrrx register. > > And as a second step, every time when musb_peri_rx_ep() is called and > there are waiting data to be processed (signaled by > MUSB_RXCSR_RXPKTRDY) either acknowledge sender (via > musb_peri_rx_ack()) that whole HW buffer was processed or set > corresponding bit in pending_intrrx that HW buffer was not fully > processed yet and next iteration is required after U-Boot allocate > space for reading HW buffer. > > This patch fixes receiving large usb buffers, e.g. file transfer via > Kermit protocol implemented by 'loadb' U-Boot command over usbtty > serial console. Reviewed-by: Lukasz Majewski <lu...@denx.de> > > Signed-off-by: Pali Rohár <p...@kernel.org> > --- > drivers/usb/musb/musb_udc.c | 16 +++++++++++++++- > 1 file changed, 15 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c > index 28719cc3f6..7c74422623 100644 > --- a/drivers/usb/musb/musb_udc.c > +++ b/drivers/usb/musb/musb_udc.c > @@ -104,6 +104,8 @@ struct usb_endpoint_instance *ep0_endpoint; > static struct usb_device_instance *udc_device; > static int enabled; > > +u16 pending_intrrx; > + > #ifdef MUSB_DEBUG > static void musb_db_regs(void) > { > @@ -664,7 +666,10 @@ static void musb_peri_rx_ep(unsigned int ep) > /* The common musb fifo reader */ > read_fifo(ep, length, data); > > - musb_peri_rx_ack(ep); > + if (length == peri_rxcount) > + musb_peri_rx_ack(ep); > + else > + pending_intrrx |= (1 << ep); > > /* > * urb's actual_length is updated in > @@ -677,18 +682,24 @@ static void musb_peri_rx_ep(unsigned int ep) > serial_printf("ERROR : %s %d > no space " "in rcv buffer\n", > __PRETTY_FUNCTION__, > ep); + > + pending_intrrx |= (1 << ep); > } > } else { > if (debug_level > 0) > serial_printf("ERROR : %s %d problem > with " "endpoint\n", > __PRETTY_FUNCTION__, > ep); + > + pending_intrrx |= (1 << ep); > } > > } else { > if (debug_level > 0) > serial_printf("ERROR : %s %d with nothing to > do\n", __PRETTY_FUNCTION__, ep); > + > + musb_peri_rx_ack(ep); > } > } > > @@ -770,6 +781,9 @@ void udc_irq(void) > intrrx = readw(&musbr->intrrx); > intrtx = readw(&musbr->intrtx); > > + intrrx |= pending_intrrx; > + pending_intrrx = 0; > + > if (intrrx) > musb_peri_rx(intrrx); > Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lu...@denx.de
pgpaD_rshHxnV.pgp
Description: OpenPGP digital signature