Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
From 47822c33905518870488414be4255301c536dec7 Mon Sep 17 00:00:00 2001
From: Augment Agent <agent@augmentcode.com>
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;
}