The Siglent SDM4065A-SC hangs its OUT endpoint when xHCI sends a packet larger than the 64 bytes it advertises. Every transfer after that times out until a USB reset: usbtmc 1-1.3:1.0: Unable to send data, error -110 usbtmc 1-1.3:1.0: send_request_dev_dep_msg_in returned -110 Limit usbtmc_write() to URBs of the advertised packet size on this device and send them one at a time. Some devices with this bug also stall on back-to-back OUT packets. Cc: stable@vger.kernel.org Signed-off-by: Nicolai Buchwitz --- The write path never handled this device, so there is no Fixes: target. --- drivers/usb/class/usbtmc.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 7a2ea14aa524b..679ab5908e203 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1145,14 +1145,15 @@ static ssize_t usbtmc_generic_write(struct usbtmc_file_data *file_data, const void __user *user_buffer, u32 transfer_size, u32 *transferred, - u32 flags) + u32 flags, bool packet_mode) { struct usbtmc_device_data *data = file_data->data; + const u32 bufsize = packet_mode ? data->out_wMaxPacketSize : + USBTMC_BUFSIZE; struct device *dev; u32 done = 0; u32 remaining; unsigned long expire; - const u32 bufsize = USBTMC_BUFSIZE; struct urb *urb = NULL; int retval = 0; u32 timeout; @@ -1190,6 +1191,14 @@ static ssize_t usbtmc_generic_write(struct usbtmc_file_data *file_data, u32 this_part, aligned; u8 *buffer = NULL; + /* Some packet mode devices stall on back-to-back OUT packets */ + if (packet_mode && + !usb_wait_anchor_empty_timeout(&file_data->submitted, + timeout)) { + retval = -ETIMEDOUT; + goto error; + } + if (flags & USBTMC_FLAG_ASYNC) { if (down_trylock(&file_data->limit_write_sem)) { retval = (done)?(0):(-EAGAIN); @@ -1309,7 +1318,7 @@ static ssize_t usbtmc_ioctl_generic_write(struct usbtmc_file_data *file_data, retval = usbtmc_generic_write(file_data, msg.message, msg.transfer_size, &msg.transferred, - msg.flags); + msg.flags, false); if (put_user(msg.transferred, &((struct usbtmc_message __user *)arg)->transferred)) @@ -1605,6 +1614,9 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, buffer = urb->transfer_buffer; buflen = urb->transfer_buffer_length; + if (data->packet_io) + buflen = data->out_wMaxPacketSize; + if (count > INT_MAX) { transfersize = INT_MAX; buffer[8] = 0; @@ -1671,7 +1683,7 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, /* call generic_write even when remaining = 0 */ retval = usbtmc_generic_write(file_data, buf + transfersize, remaining, - &done, USBTMC_FLAG_APPEND); + &done, USBTMC_FLAG_APPEND, data->packet_io); /* truncate alignment bytes */ if (done > remaining) done = remaining; -- 2.53.0