diff --git a/external/patches/linux/0018-Improve-f_accessory-write-queue-handling.patch b/external/patches/linux/0018-Improve-f_accessory-write-queue-handling.patch new file mode 100644 index 0000000..2e1f19f --- /dev/null +++ b/external/patches/linux/0018-Improve-f_accessory-write-queue-handling.patch @@ -0,0 +1,101 @@ +From 47822c33905518870488414be4255301c536dec7 Mon Sep 17 00:00:00 2001 +From: Augment Agent +Date: Mon, 16 Mar 2026 23:10:00 +0000 +Subject: [PATCH] usb: gadget: improve accessory write queue handling + + +--- + drivers/usb/gadget/function/f_accessory.c | 36 ++++++++++---------- + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c +index ce7814c..14be99b 100644 +--- a/drivers/usb/gadget/function/f_accessory.c ++++ b/drivers/usb/gadget/function/f_accessory.c +@@ -55,7 +55,7 @@ + #define INTERFACE_STRING_INDEX 0 + + /* number of tx and rx requests to allocate */ +-#define TX_REQ_MAX 4 ++#define TX_REQ_MAX 16 // was likely 4 or 8 + #define RX_REQ_MAX 2 + + struct acc_hid_dev { +@@ -790,21 +790,28 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, + ssize_t r = count; + unsigned xfer; + int ret; ++ int submitted = 0; + + pr_debug("acc_write(%zu)\n", count); + + if (!dev->online || dev->disconnected) { +- pr_debug("acc_write disconnected or not online"); + return -ENODEV; + } + + while (count > 0) { +- /* get an idle tx request to use */ +- req = 0; +- ret = wait_event_interruptible(dev->write_wq, +- ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); ++ /* Only wait if we've saturated the queue */ ++ if (submitted >= TX_REQ_MAX - 1) { ++ ret = wait_event_interruptible(dev->write_wq, ++ ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); ++ } else { ++ req = req_get(dev, &dev->tx_idle); ++ if (!req) { ++ ret = wait_event_interruptible(dev->write_wq, ++ ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); ++ } ++ } ++ + if (!dev->online || dev->disconnected) { +- pr_debug("acc_write dev->error\n"); + r = -EIO; + break; + } +@@ -816,16 +823,14 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, + + if (count > BULK_BUFFER_SIZE) { + xfer = BULK_BUFFER_SIZE; +- /* ZLP, They will be more TX requests so not yet. */ + req->zero = 0; + } else { + xfer = count; +- /* If the data length is a multple of the +- * maxpacket size then send a zero length packet(ZLP). +- */ + req->zero = ((xfer % dev->ep_in->maxpacket) == 0); + } ++ + if (copy_from_user(req->buf, buf, xfer)) { ++ req_put(dev, &dev->tx_idle, req); + r = -EFAULT; + break; + } +@@ -833,21 +838,16 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, + req->length = xfer; + ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); + if (ret < 0) { +- pr_debug("acc_write: xfer error %d\n", ret); ++ req_put(dev, &dev->tx_idle, req); + r = -EIO; + break; + } + + buf += xfer; + count -= xfer; +- +- /* zero this so we don't try to free it on error exit */ +- req = 0; ++ submitted++; + } + +- if (req) +- req_put(dev, &dev->tx_idle, req); +- + pr_debug("acc_write returning %zd\n", r); + return r; + }