summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorTomasz Moń <desowin@gmail.com>2021-06-07 19:42:29 +0200
committerTomasz Moń <desowin@gmail.com>2021-06-09 10:21:06 +0000
commitefa173a9237278c9b98c5e7660103e66be541597 (patch)
treee0915ad0993670b88ab04da8efe790e1cc654dd5 /firmware/target/arm
parent7f3d0ce814ef2f4edf5128f3a2970f3673b9353b (diff)
downloadrockbox-efa173a9237278c9b98c5e7660103e66be541597.tar.gz
rockbox-efa173a9237278c9b98c5e7660103e66be541597.tar.bz2
rockbox-efa173a9237278c9b98c5e7660103e66be541597.zip
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
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c23
1 files changed, 19 insertions, 4 deletions
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;