From efa173a9237278c9b98c5e7660103e66be541597 Mon Sep 17 00:00:00 2001 From: Tomasz Moń Date: Mon, 7 Jun 2021 19:42:29 +0200 Subject: Sansa Connect: Fix bulk transfers greater than 64 bytes Correctly set endpoint maximum packet size so host will not consider end of transfer after receiving first packet when transfer is larger than 64 bytes (at High Speed the endpoint max packet size was set to 64 but according to descriptor it is 512). Split DMA transfers up to CPPI_MAX_FRAG so we get single interrupt after each call to tnetv_cppi_send(). Change-Id: I385b66bc5d71975a4e3e9167efac0b1334bd3ffc --- .../tms320dm320/sansa-connect/tnetv105_usb_drv.c | 23 ++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'firmware') diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c index 4fdf73cb50..bf1305824d 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c @@ -591,7 +591,7 @@ static int tnetv_ep_start_xmit(int epn, void *buf, int size) { dma_addr_t buffer = (dma_addr_t)buf; commit_discard_dcache_range(buf, size); - if ((buffer >= CONFIG_SDRAM_START) && (buffer <= CONFIG_SDRAM_START + SDRAM_SIZE)) + if ((buffer >= CONFIG_SDRAM_START) && (buffer + size < CONFIG_SDRAM_START + SDRAM_SIZE)) { if (tnetv_cppi_send(&cppi, (epn - 1), buffer, size, 0)) { @@ -675,6 +675,7 @@ static int tnetv_gadget_ep_enable(int epn, bool in) { UsbEpCfgCtrlType epCfg; int flags; + enum usb_device_speed speed; if (epn == 0 || epn >= USB_NUM_ENDPOINTS) { @@ -684,7 +685,8 @@ static int tnetv_gadget_ep_enable(int epn, bool in) flags = disable_irq_save(); /* set the maxpacket for this endpoint based on the current speed */ - ep_runtime[epn].max_packet_size = MAX_PACKET(epn, usb_drv_port_speed()); + speed = usb_drv_port_speed() ? USB_SPEED_HIGH : USB_SPEED_FULL; + ep_runtime[epn].max_packet_size = MAX_PACKET(epn, speed); /* Enable the endpoint */ epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn)); @@ -819,8 +821,21 @@ static void ep_write(int epn) } else { - /* DMA takes care of splitting the buffer into packets */ - tx_size = ep->tx_remaining; + /* DMA takes care of splitting the buffer into packets, + * but only up to CPPI_MAX_FRAG. After the data is sent + * a single interrupt is generated. There appears to be + * splitting code in the tnetv_cppi_send() function but + * it is somewhat suspicious (it doesn't seem like it + * will work with requests larger than 2*CPPI_MAX_FRAG). + * Also, if tnetv_cppi_send() does the splitting, we will + * get an interrupt after CPPI_MAX_FRAG but before the + * full request is sent. + * + * CPPI_MAX_FRAG is multiple of both 64 and 512 so we + * don't have to worry about this split prematurely ending + * the transfer. + */ + tx_size = MIN(CPPI_MAX_FRAG, ep->tx_remaining); } tnetv_ep_start_xmit(epn, ep->tx_buf, tx_size); ep->tx_remaining -= tx_size; -- cgit v1.2.3