265 lines
9.3 KiB
Diff
265 lines
9.3 KiB
Diff
|
From e0a164b50a1f11ead9f47da0233f6f954e04127f Mon Sep 17 00:00:00 2001
|
||
|
From: Chris Dickens <christopher.a.dickens@gmail.com>
|
||
|
Date: Thu, 16 Jan 2020 14:17:12 -0800
|
||
|
Subject: [PATCH 10/10] linux_usbfs: Wait until all URBs have been reaped
|
||
|
before freeing them
|
||
|
|
||
|
Prior to this change, the URBs allocated for an individual transfer were
|
||
|
freed when the last URB in the transfer was reaped. Normally this causes
|
||
|
no issues because URBs are reaped in the order they were submitted. If
|
||
|
the device is disconnected while multiple URBs are queued, these URBs
|
||
|
may be reaped in an order that does not match that of submission.
|
||
|
|
||
|
Change the logic to free the URBs when all the URBs of a transfer have
|
||
|
been reaped rather than the last one. While in here, improve some debug
|
||
|
messages.
|
||
|
|
||
|
Closes #607
|
||
|
|
||
|
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
|
||
|
(cherry picked from commit 9eda802d947d9c4212eb3f821fa51956029dade0)
|
||
|
---
|
||
|
libusb/os/linux_usbfs.c | 60 ++++++++++++++++++++---------------------
|
||
|
libusb/version_nano.h | 2 +-
|
||
|
2 files changed, 31 insertions(+), 31 deletions(-)
|
||
|
|
||
|
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
|
||
|
index 53530cd..4179b9a 100644
|
||
|
--- a/libusb/os/linux_usbfs.c
|
||
|
+++ b/libusb/os/linux_usbfs.c
|
||
|
@@ -944,7 +944,7 @@ static int usbfs_get_active_config(struct libusb_device *dev, int fd)
|
||
|
|
||
|
/* we hit this error path frequently with buggy devices :( */
|
||
|
usbi_warn(DEVICE_CTX(dev),
|
||
|
- "get_configuration failed ret=%d errno=%d", r, errno);
|
||
|
+ "get configuration failed, errno=%d", errno);
|
||
|
priv->active_config = -1;
|
||
|
} else {
|
||
|
if (active_config > 0) {
|
||
|
@@ -1401,7 +1401,7 @@ static int initialize_handle(struct libusb_device_handle *handle, int fd)
|
||
|
if (errno == ENOTTY)
|
||
|
usbi_dbg("getcap not available");
|
||
|
else
|
||
|
- usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno);
|
||
|
+ usbi_err(HANDLE_CTX(handle), "getcap failed, errno=%d", errno);
|
||
|
hpriv->caps = 0;
|
||
|
if (supports_flag_zero_packet)
|
||
|
hpriv->caps |= USBFS_CAP_ZERO_PACKET;
|
||
|
@@ -1426,7 +1426,7 @@ static int op_wrap_sys_device(struct libusb_context *ctx,
|
||
|
if (r < 0) {
|
||
|
r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
|
||
|
if (r < 0) {
|
||
|
- usbi_err(ctx, "connectinfo failed (%d)", errno);
|
||
|
+ usbi_err(ctx, "connectinfo failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_IO;
|
||
|
}
|
||
|
/* There is no ioctl to get the bus number. We choose 0 here
|
||
|
@@ -1537,7 +1537,8 @@ static int op_set_configuration(struct libusb_device_handle *handle, int config)
|
||
|
else if (errno == ENODEV)
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
- usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno);
|
||
|
+ usbi_err(HANDLE_CTX(handle),
|
||
|
+ "set configuration failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
|
||
|
@@ -1560,7 +1561,7 @@ static int claim_interface(struct libusb_device_handle *handle, int iface)
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "claim interface failed, error %d errno %d", r, errno);
|
||
|
+ "claim interface failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
return 0;
|
||
|
@@ -1575,7 +1576,7 @@ static int release_interface(struct libusb_device_handle *handle, int iface)
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "release interface failed, error %d errno %d", r, errno);
|
||
|
+ "release interface failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
return 0;
|
||
|
@@ -1598,7 +1599,7 @@ static int op_set_interface(struct libusb_device_handle *handle, int iface,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "setintf failed error %d errno %d", r, errno);
|
||
|
+ "set interface failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
|
||
|
@@ -1618,7 +1619,7 @@ static int op_clear_halt(struct libusb_device_handle *handle,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "clear_halt failed error %d errno %d", r, errno);
|
||
|
+ "clear halt failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
|
||
|
@@ -1650,7 +1651,7 @@ static int op_reset_device(struct libusb_device_handle *handle)
|
||
|
}
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "reset failed error %d errno %d", r, errno);
|
||
|
+ "reset failed, errno=%d", errno);
|
||
|
ret = LIBUSB_ERROR_OTHER;
|
||
|
goto out;
|
||
|
}
|
||
|
@@ -1708,7 +1709,7 @@ static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "streams-ioctl failed error %d errno %d", r, errno);
|
||
|
+ "streams-ioctl failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
return r;
|
||
|
@@ -1770,7 +1771,7 @@ static int op_kernel_driver_active(struct libusb_device_handle *handle,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "get driver failed error %d errno %d", r, errno);
|
||
|
+ "get driver failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
|
||
|
@@ -1804,7 +1805,7 @@ static int op_detach_kernel_driver(struct libusb_device_handle *handle,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "detach failed error %d errno %d", r, errno);
|
||
|
+ "detach failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
}
|
||
|
|
||
|
@@ -1834,7 +1835,7 @@ static int op_attach_kernel_driver(struct libusb_device_handle *handle,
|
||
|
return LIBUSB_ERROR_BUSY;
|
||
|
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "attach failed error %d errno %d", r, errno);
|
||
|
+ "attach failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
} else if (r == 0) {
|
||
|
return LIBUSB_ERROR_NOT_FOUND;
|
||
|
@@ -1863,7 +1864,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
}
|
||
|
usbi_err(HANDLE_CTX(handle),
|
||
|
- "disconnect-and-claim failed errno %d", errno);
|
||
|
+ "disconnect-and-claim failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_OTHER;
|
||
|
} else if (r == 0)
|
||
|
return 0;
|
||
|
@@ -2083,7 +2084,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
|
||
|
r = LIBUSB_ERROR_NO_MEM;
|
||
|
} else {
|
||
|
usbi_err(TRANSFER_CTX(transfer),
|
||
|
- "submiturb failed error %d errno=%d", r, errno);
|
||
|
+ "submiturb failed, errno=%d", errno);
|
||
|
r = LIBUSB_ERROR_IO;
|
||
|
}
|
||
|
|
||
|
@@ -2241,7 +2242,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
||
|
r = LIBUSB_ERROR_INVALID_PARAM;
|
||
|
} else {
|
||
|
usbi_err(TRANSFER_CTX(transfer),
|
||
|
- "submiturb failed error %d errno=%d", r, errno);
|
||
|
+ "submiturb failed, errno=%d", errno);
|
||
|
r = LIBUSB_ERROR_IO;
|
||
|
}
|
||
|
|
||
|
@@ -2316,7 +2317,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer)
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
usbi_err(TRANSFER_CTX(transfer),
|
||
|
- "submiturb failed error %d errno=%d", r, errno);
|
||
|
+ "submiturb failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_IO;
|
||
|
}
|
||
|
return 0;
|
||
|
@@ -2498,10 +2499,10 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer,
|
||
|
goto cancel_remaining;
|
||
|
}
|
||
|
|
||
|
- /* if we're the last urb or we got less data than requested then we're
|
||
|
+ /* if we've reaped all urbs or we got less data than requested then we're
|
||
|
* done */
|
||
|
- if (urb_idx == tpriv->num_urbs - 1) {
|
||
|
- usbi_dbg("last URB in transfer --> complete!");
|
||
|
+ if (tpriv->num_retired == tpriv->num_urbs) {
|
||
|
+ usbi_dbg("all URBs in transfer reaped --> complete!");
|
||
|
goto completed;
|
||
|
} else if (urb->actual_length < urb->buffer_length) {
|
||
|
usbi_dbg("short transfer %d/%d --> complete!",
|
||
|
@@ -2577,15 +2578,15 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
|
||
|
break;
|
||
|
case -ENODEV:
|
||
|
case -ESHUTDOWN:
|
||
|
- usbi_dbg("device removed");
|
||
|
+ usbi_dbg("packet %d - device removed", i);
|
||
|
lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
|
||
|
break;
|
||
|
case -EPIPE:
|
||
|
- usbi_dbg("detected endpoint stall");
|
||
|
+ usbi_dbg("packet %d - detected endpoint stall", i);
|
||
|
lib_desc->status = LIBUSB_TRANSFER_STALL;
|
||
|
break;
|
||
|
case -EOVERFLOW:
|
||
|
- usbi_dbg("overflow error");
|
||
|
+ usbi_dbg("packet %d - overflow error", i);
|
||
|
lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
|
||
|
break;
|
||
|
case -ETIME:
|
||
|
@@ -2594,12 +2595,12 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
|
||
|
case -ECOMM:
|
||
|
case -ENOSR:
|
||
|
case -EXDEV:
|
||
|
- usbi_dbg("low-level USB error %d", urb_desc->status);
|
||
|
+ usbi_dbg("packet %d - low-level USB error %d", i, urb_desc->status);
|
||
|
lib_desc->status = LIBUSB_TRANSFER_ERROR;
|
||
|
break;
|
||
|
default:
|
||
|
usbi_warn(TRANSFER_CTX(transfer),
|
||
|
- "unrecognised urb status %d", urb_desc->status);
|
||
|
+ "packet %d - unrecognised urb status %d", i, urb_desc->status);
|
||
|
lib_desc->status = LIBUSB_TRANSFER_ERROR;
|
||
|
break;
|
||
|
}
|
||
|
@@ -2643,9 +2644,9 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
- /* if we're the last urb then we're done */
|
||
|
- if (urb_idx == num_urbs) {
|
||
|
- usbi_dbg("last URB in transfer --> complete!");
|
||
|
+ /* if we've reaped all urbs then we're done */
|
||
|
+ if (tpriv->num_retired == num_urbs) {
|
||
|
+ usbi_dbg("all URBs in transfer reaped --> complete!");
|
||
|
free_iso_urbs(tpriv);
|
||
|
usbi_mutex_unlock(&itransfer->lock);
|
||
|
return usbi_handle_transfer_completion(itransfer, status);
|
||
|
@@ -2733,8 +2734,7 @@ static int reap_for_handle(struct libusb_device_handle *handle)
|
||
|
if (errno == ENODEV)
|
||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||
|
|
||
|
- usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d",
|
||
|
- r, errno);
|
||
|
+ usbi_err(HANDLE_CTX(handle), "reap failed, errno=%d", errno);
|
||
|
return LIBUSB_ERROR_IO;
|
||
|
}
|
||
|
|
||
|
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
|
||
|
index 3247cec..f496998 100644
|
||
|
--- a/libusb/version_nano.h
|
||
|
+++ b/libusb/version_nano.h
|
||
|
@@ -1 +1 @@
|
||
|
-#define LIBUSB_NANO 11427
|
||
|
+#define LIBUSB_NANO 11428
|
||
|
--
|
||
|
2.26.1
|
||
|
|