This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 1df640186ea usbdev_fs: allow multi-packet bulk requests
1df640186ea is described below
commit 1df640186ea5c36d1ceac48a36f8b13ff916fa3f
Author: wangjianyu3 <[email protected]>
AuthorDate: Fri Nov 6 15:45:46 2026 +0800
usbdev_fs: allow multi-packet bulk requests
Bulk requests were fixed to one maxpacket, capping streams near 10MB/s.
Size them by USBDEV_FS_BULK_REQLEN; 0 uses the descriptor packet size.
Download-only 32MiB, flash stubbed, NRDREQS=4, BULK_REQLEN 0 vs 16384:
DOWNLOAD_MAX before after
40960 10.6MB/s 21.5MB/s
262144 12.1MB/s 35.5MB/s
Assisted-by: OpenCode:mimo-2.6-pro Kiro:claude-opus-5.5
Signed-off-by: wangjianyu3 <[email protected]>
---
drivers/usbdev/Kconfig | 10 +++++++
drivers/usbdev/usbdev_fs.c | 74 ++++++++++++++++++++++++++++++----------------
2 files changed, 58 insertions(+), 26 deletions(-)
diff --git a/drivers/usbdev/Kconfig b/drivers/usbdev/Kconfig
index 6a369baf989..4ca32477381 100644
--- a/drivers/usbdev/Kconfig
+++ b/drivers/usbdev/Kconfig
@@ -1833,6 +1833,16 @@ config USBDEV_FS_NEP0REQS
---help---
The number of ep0 requests that can be in flight
+config USBDEV_FS_BULK_REQLEN
+ int "Request buffer size per endpoint"
+ default 0
+ range 0 32768
+ ---help---
+ Request buffer size of each endpoint, rounded up to a multiple
+ of the default request size. Reads and writes use up to this
+ many bytes per request. 0 keeps the default size (the
+ configuration descriptor size on ep0).
+
endif #USBDEV_FS
menuconfig USBMTP
diff --git a/drivers/usbdev/usbdev_fs.c b/drivers/usbdev/usbdev_fs.c
index e8294360142..555b77f107c 100644
--- a/drivers/usbdev/usbdev_fs.c
+++ b/drivers/usbdev/usbdev_fs.c
@@ -55,7 +55,7 @@ struct usbdev_fs_req_s
{
sq_entry_t node; /* Implements a singly linked list */
FAR struct usbdev_req_s *req; /* The contained request */
- uint16_t offset; /* Offset to valid data in the RX request
*/
+ size_t offset; /* Offset to valid data in the RX request
*/
};
struct usbdev_ctrlreq_s
@@ -84,6 +84,8 @@ struct usbdev_fs_ep_s
FAR usbdev_fs_waiter_sem_t *sems; /* List of blocking request */
struct sq_queue_s reqq; /* Available request containers */
FAR struct usbdev_fs_req_s *reqbuffer; /* Request buffer */
+ size_t reqsize;
+ uint16_t reqnum;
FAR struct pollfd_s *fds[CONFIG_USBDEV_FS_NPOLLWAITERS];
spinlock_t spinlock;
@@ -217,7 +219,7 @@ static void usbdev_fs_notify(FAR struct usbdev_fs_ep_s
*fs_ep,
static int usbdev_fs_submit_wrreq(FAR struct usbdev_ep_s *ep,
FAR struct usbdev_fs_req_s *container,
- uint16_t len)
+ size_t len)
{
FAR struct usbdev_req_s *req = container->req;
@@ -236,11 +238,25 @@ static int usbdev_fs_submit_wrreq(FAR struct usbdev_ep_s
*ep,
****************************************************************************/
static int usbdev_fs_submit_rdreq(FAR struct usbdev_ep_s *ep,
- FAR struct usbdev_fs_req_s *container)
+ FAR struct usbdev_fs_req_s *container,
+ size_t want)
{
+ FAR struct usbdev_fs_ep_s *fs_ep = (FAR struct usbdev_fs_ep_s *)ep->fs;
FAR struct usbdev_req_s *req = container->req;
+ size_t pending = 0;
+ uint16_t i;
+
+ for (i = 0; i < fs_ep->reqnum; i++)
+ {
+ if (&fs_ep->reqbuffer[i] != container)
+ {
+ pending += fs_ep->reqbuffer[i].req->len;
+ }
+ }
- req->len = ep->maxpacket;
+ want = ALIGN_UP(want, ep->maxpacket);
+ req->len = want > pending ? MIN(want - pending, fs_ep->reqsize) :
+ ep->maxpacket;
return EP_SUBMIT(ep, req);
}
@@ -317,7 +333,7 @@ restart_req:
/* Restart request */
- usbdev_fs_submit_rdreq(fs_ep->ep, container);
+ usbdev_fs_submit_rdreq(fs_ep->ep, container, 0);
}
/****************************************************************************
@@ -627,7 +643,8 @@ static ssize_t usbdev_fs_read(FAR struct file *filep, FAR
char *buffer,
while (!sq_empty(queue))
{
FAR struct usbdev_fs_req_s *container;
- uint16_t reqlen;
+ size_t reqlen;
+ size_t rlen;
if (is_ep0)
{
@@ -660,6 +677,7 @@ static ssize_t usbdev_fs_read(FAR struct file *filep, FAR
char *buffer,
container = container_of(sq_peek(queue),
struct usbdev_fs_req_s, node);
+ rlen = container->req->len;
reqlen = container->req->xfrd - container->offset;
if (reqlen > len)
@@ -697,7 +715,7 @@ static ssize_t usbdev_fs_read(FAR struct file *filep, FAR
char *buffer,
sq_remfirst(queue);
spin_unlock_irqrestore(&fs_ep->spinlock, flags);
- ret = usbdev_fs_submit_rdreq(fs_ep->ep, container);
+ ret = usbdev_fs_submit_rdreq(fs_ep->ep, container, len);
if (ret < 0)
{
/* TODO handle error */
@@ -710,7 +728,7 @@ static ssize_t usbdev_fs_read(FAR struct file *filep, FAR
char *buffer,
* returned directly.
*/
- if (reqlen < fs_ep->ep->maxpacket)
+ if (reqlen < rlen)
{
break;
}
@@ -736,7 +754,7 @@ static ssize_t usbdev_fs_write(FAR struct file *filep,
FAR struct usbdev_fs_req_s *container;
FAR struct usbdev_req_s *req;
irqstate_t flags;
- int wlen = 0;
+ size_t wlen = 0;
int ret;
ret = nxmutex_lock(&fs_ep->lock);
@@ -781,7 +799,7 @@ static ssize_t usbdev_fs_write(FAR struct file *filep,
while (!sq_empty(&fs_ep->reqq))
{
- uint16_t cur_len;
+ size_t cur_len;
/* Get available TX request slot */
@@ -796,13 +814,10 @@ static ssize_t usbdev_fs_write(FAR struct file *filep,
/* Fill the request with data */
- if (len > fs_ep->ep->maxpacket)
- {
- cur_len = fs_ep->ep->maxpacket;
- }
- else
+ cur_len = ALIGN_DOWN(fs_ep->reqsize, fs_ep->ep->maxpacket);
+ if (len <= fs_ep->reqsize || cur_len == 0)
{
- cur_len = len;
+ cur_len = MIN(len, fs_ep->reqsize);
}
memcpy(req->buf, &buffer[wlen], cur_len);
@@ -995,14 +1010,15 @@ static int usbdev_fs_ep_bind(FAR struct usbdev_s *dev,
uint8_t epno,
FAR const struct usbdev_epinfo_s *epinfo,
FAR struct usbdev_fs_ep_s *fs_ep)
{
+ uint16_t i;
+
#if defined(CONFIG_USBDEV_SUPERSPEED)
- size_t reqsize = epinfo->sssize;
+ fs_ep->reqsize = epinfo->sssize;
#elif defined(CONFIG_USBDEV_DUALSPEED)
- size_t reqsize = epinfo->hssize;
+ fs_ep->reqsize = epinfo->hssize;
#else
- size_t reqsize = epinfo->fssize;
+ fs_ep->reqsize = epinfo->fssize;
#endif
- uint16_t i;
/* Initialize fs ep lock */
@@ -1044,22 +1060,22 @@ static int usbdev_fs_ep_bind(FAR struct usbdev_s *dev,
uint8_t epno,
{
if (epinfo->compdesc.mxburst >= USB_SS_BULK_EP_MAXBURST)
{
- reqsize = reqsize * USB_SS_BULK_EP_MAXBURST;
+ fs_ep->reqsize *= USB_SS_BULK_EP_MAXBURST;
}
else
{
- reqsize = reqsize * (epinfo->compdesc.mxburst + 1);
+ fs_ep->reqsize *= (epinfo->compdesc.mxburst + 1);
}
}
else if (transtpye == USB_EP_ATTR_XFER_INT)
{
if (epinfo->compdesc.mxburst >= USB_SS_INT_EP_MAXBURST)
{
- reqsize = reqsize * USB_SS_INT_EP_MAXBURST;
+ fs_ep->reqsize *= USB_SS_INT_EP_MAXBURST;
}
else
{
- reqsize = reqsize * (epinfo->compdesc.mxburst + 1);
+ fs_ep->reqsize *= (epinfo->compdesc.mxburst + 1);
}
}
}
@@ -1067,6 +1083,12 @@ static int usbdev_fs_ep_bind(FAR struct usbdev_s *dev,
uint8_t epno,
fs_ep->ep->fs = fs_ep;
+#if CONFIG_USBDEV_FS_BULK_REQLEN > 0
+ fs_ep->reqsize = ALIGN_UP(CONFIG_USBDEV_FS_BULK_REQLEN, fs_ep->reqsize);
+#endif
+
+ fs_ep->reqnum = epinfo->reqnum;
+
/* Initialize request buffer */
fs_ep->reqbuffer =
@@ -1093,7 +1115,7 @@ static int usbdev_fs_ep_bind(FAR struct usbdev_s *dev,
uint8_t epno,
FAR struct usbdev_fs_req_s *container;
container = &fs_ep->reqbuffer[i];
- container->req = usbdev_allocreq(fs_ep->ep, reqsize);
+ container->req = usbdev_allocreq(fs_ep->ep, fs_ep->reqsize);
if (container->req == NULL)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDALLOCREQ), -ENOMEM);
@@ -1316,7 +1338,7 @@ static int usbdev_fs_classsetconfig(FAR struct
usbdev_fs_dev_s *fs,
container = &fs_ep->reqbuffer[j];
container->req->callback = usbdev_fs_rdcomplete;
- usbdev_fs_submit_rdreq(fs_ep->ep, container);
+ usbdev_fs_submit_rdreq(fs_ep->ep, container, 0);
}
}
}