mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-06-09 23:36:03 +09:00
usb: musb: Fix receiving of bigger buffers
If musb_peri_rx_ep() was called to process 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 also when HW buffer stayed unprocessed. U-Boot tried to process this buffer again when it received interrupt again, but it can receive it only when sender (host) sends 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 marks interrupt as processed. So to prevent marking interrupt in U-Boot as processed, adds a new variable pending_intrrx which would contain unprocessed bits of intrrx register. For 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 allocates 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. Signed-off-by: Pali Rohár <pali@kernel.org> Reviewed-by: Lukasz Majewski <lukma@denx.de> Acked-by: Pavel Machek <pavel@ucw.cz>
This commit is contained in:
parent
ea7125c4c6
commit
ff77bb301e
|
@ -104,6 +104,8 @@ struct usb_endpoint_instance *ep0_endpoint;
|
|||
static struct usb_device_instance *udc_device;
|
||||
static int enabled;
|
||||
|
||||
static 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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user