ast_udc_epn_kick_desc() computes tx_len as u32 bounded by AST_EP_DMA_DESC_MAX_LEN * AST_UDC_DESCS_COUNT (7680 * 256, roughly 1.88 MB) and hands it to ast_dma_descriptor_setup(), whose tx_len parameter is u16. The length is truncated to the low 16 bits before the descriptor list is built, so a descriptor-mode IN request larger than 64 KB is described -- and therefore transferred -- as only tx_len % 64 KB bytes. The caller still accounts the full, untruncated length: req->actual_dma_length += tx_len; so req->actual_dma_length never equals req->req.actual and the "more requests" check in ast_udc_epn_handle_desc() never kicks the next stage. The request never completes and the endpoint queue stops draining. The same handler accumulates the per-descriptor transfer lengths of a stage into a u16 total_len. Each descriptor carries up to 8191 bytes (EP_DESC1_IN_LEN mask 0x1fff) and up to AST_UDC_DESCS_COUNT (256) descriptors are walked, so once the truncation above is fixed the sum can exceed the u16 range: a full stage covers 7680 * 256 bytes, which wraps modulo 64 KB to a value smaller than ep->ep.maxpacket. The short-packet check then believes the stage was short, completes the request before the whole transfer has finished, and adds a length to req->req.actual that does not match what was really moved. Widen both the tx_len parameter and the total_len accumulator to u32. Fixes: 055276c13205 ("usb: gadget: add Aspeed ast2600 udc driver") Cc: stable@vger.kernel.org Reviewed-by: Guanglei Zhu Signed-off-by: Liu Chao --- drivers/usb/gadget/udc/aspeed_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c index 54f81e668009..f8c58158bd51 100644 --- a/drivers/usb/gadget/udc/aspeed_udc.c +++ b/drivers/usb/gadget/udc/aspeed_udc.c @@ -472,7 +472,7 @@ static void ast_udc_ep_free_request(struct usb_ep *_ep, } static int ast_dma_descriptor_setup(struct ast_udc_ep *ep, u32 dma_buf, - u16 tx_len, struct ast_udc_request *req) + u32 tx_len, struct ast_udc_request *req) { struct ast_udc_dev *udc = ep->udc; struct device *dev = &udc->pdev->dev; @@ -899,7 +899,7 @@ static void ast_udc_epn_handle_desc(struct ast_udc_dev *udc, u16 ep_num) struct ast_udc_request *req; u32 proc_sts, wr_ptr, rd_ptr; u32 len_in_desc, ctrl; - u16 total_len = 0; + u32 total_len = 0; int i; if (list_empty(&ep->queue)) { -- 2.50.1