usb: bugfixes for xhci, usb pass-through and usb redirection.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJeHGtbAAoJEEy22O7T6HE43vQQANtKv7pd2FsvgXsXc8nK1VOP oiGQdL96pUCHHQvPWOE9z+PhmwCoyJ3NSE2p1iDkiIHqyNykZSvlO9FADwPeKnUu b5oJpj1Joewrzdb7N8/Fs0TVq6/4KFiTXUGf1mdAi1TIrFDGOCtLllQMOj2nlMuV kfCKd8hbv41OSy4buDZb7BA4sKREynfZneKvFwx/0Er1Xv1wjIPIHgnZiDSqEQf4 /uXGBdYIdMPTaHAK0NJfM1OjIMmjLnd30w4MhjhJRUeRScQhD0+DOZiSmV1mJb6P ddLVystut5+wPPH8cadKqCW6xxwkwaxYe8Mz97j0dyHG4dt9n4iwOb+BjNxRRG/S kLK5TlStnRk8PyzH0qhHKH2YtTpHVfULEM7FRS2MQ6fSLrC8RaW6i9WzfLF+ye42 F7G6AYjU5Re5pFO2kqhcvE/UEFV0Al+AWjRzQDDq0bnRflGz4PCZgckOBfE6OjNp eUpMbfCAeaWcatIIIZYGbl1HXDAdgig4REpJCoM8HgHZV2Fc2e8p/BeXm60t2XV8 YNjfg1gyUSfL1gEYZno+L8ixO5tv4Y+RXRTjt8Hx6zQkNEbEW4nJf7A31SiN2/b3 1l9rPPsn43q3KIOC3Ylg57tSDUQnTBRrCThy1/wYrp9Av8hqb7dNrjFvkoLHRY5x R9cU7rsvnPRqwWbZVUOl =zECN -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/usb-20200113-pull-request' into staging usb: bugfixes for xhci, usb pass-through and usb redirection. # gpg: Signature made Mon 13 Jan 2020 13:06:35 GMT # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/usb-20200113-pull-request: xhci: recheck slot status xhci: Fix memory leak in xhci_kick_epctx when poweroff GuestOS usbredir: Prevent recursion in usbredir_write usb-redir: remove 'remote wakeup' flag from configuration descriptor usb-host: remove 'remote wakeup' flag from configuration descriptor Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3c8a657598
@ -32,6 +32,8 @@ GlobalProperty hw_compat_4_2[] = {
|
|||||||
{ "virtio-blk-device", "seg-max-adjust", "off"},
|
{ "virtio-blk-device", "seg-max-adjust", "off"},
|
||||||
{ "virtio-scsi-device", "seg_max_adjust", "off"},
|
{ "virtio-scsi-device", "seg_max_adjust", "off"},
|
||||||
{ "vhost-blk-device", "seg_max_adjust", "off"},
|
{ "vhost-blk-device", "seg_max_adjust", "off"},
|
||||||
|
{ "usb-host", "suppress-remote-wake", "off" },
|
||||||
|
{ "usb-redir", "suppress-remote-wake", "off" },
|
||||||
};
|
};
|
||||||
const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2);
|
const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2);
|
||||||
|
|
||||||
|
@ -1861,6 +1861,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
|
|||||||
xhci_kick_epctx(epctx, streamid);
|
xhci_kick_epctx(epctx, streamid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool xhci_slot_ok(XHCIState *xhci, int slotid)
|
||||||
|
{
|
||||||
|
return (xhci->slots[slotid - 1].uport &&
|
||||||
|
xhci->slots[slotid - 1].uport->dev &&
|
||||||
|
xhci->slots[slotid - 1].uport->dev->attached);
|
||||||
|
}
|
||||||
|
|
||||||
static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||||
{
|
{
|
||||||
XHCIState *xhci = epctx->xhci;
|
XHCIState *xhci = epctx->xhci;
|
||||||
@ -1878,9 +1885,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
|||||||
|
|
||||||
/* If the device has been detached, but the guest has not noticed this
|
/* If the device has been detached, but the guest has not noticed this
|
||||||
yet the 2 above checks will succeed, but we must NOT continue */
|
yet the 2 above checks will succeed, but we must NOT continue */
|
||||||
if (!xhci->slots[epctx->slotid - 1].uport ||
|
if (!xhci_slot_ok(xhci, epctx->slotid)) {
|
||||||
!xhci->slots[epctx->slotid - 1].uport->dev ||
|
|
||||||
!xhci->slots[epctx->slotid - 1].uport->dev->attached) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1987,6 +1992,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
|||||||
} else {
|
} else {
|
||||||
xhci_fire_transfer(xhci, xfer, epctx);
|
xhci_fire_transfer(xhci, xfer, epctx);
|
||||||
}
|
}
|
||||||
|
if (!xhci_slot_ok(xhci, epctx->slotid)) {
|
||||||
|
/* surprise removal -> stop processing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (xfer->complete) {
|
if (xfer->complete) {
|
||||||
/* update ring dequeue ptr */
|
/* update ring dequeue ptr */
|
||||||
xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
|
xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
|
||||||
@ -2000,6 +2009,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
|||||||
if (xfer != NULL && xfer->running_retry) {
|
if (xfer != NULL && xfer->running_retry) {
|
||||||
DPRINTF("xhci: xfer nacked, stopping schedule\n");
|
DPRINTF("xhci: xfer nacked, stopping schedule\n");
|
||||||
epctx->retry = xfer;
|
epctx->retry = xfer;
|
||||||
|
xhci_xfer_unmap(xfer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (count++ > TRANSFER_LIMIT) {
|
if (count++ > TRANSFER_LIMIT) {
|
||||||
|
@ -88,6 +88,7 @@ struct USBHostDevice {
|
|||||||
bool needs_autoscan;
|
bool needs_autoscan;
|
||||||
bool allow_one_guest_reset;
|
bool allow_one_guest_reset;
|
||||||
bool allow_all_guest_resets;
|
bool allow_all_guest_resets;
|
||||||
|
bool suppress_remote_wake;
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
QTAILQ_ENTRY(USBHostDevice) next;
|
QTAILQ_ENTRY(USBHostDevice) next;
|
||||||
@ -386,6 +387,8 @@ static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
|
|||||||
r->p->status = status_map[xfer->status];
|
r->p->status = status_map[xfer->status];
|
||||||
r->p->actual_length = xfer->actual_length;
|
r->p->actual_length = xfer->actual_length;
|
||||||
if (r->in && xfer->actual_length) {
|
if (r->in && xfer->actual_length) {
|
||||||
|
USBDevice *udev = USB_DEVICE(s);
|
||||||
|
struct libusb_config_descriptor *conf = (void *)r->cbuf;
|
||||||
memcpy(r->cbuf, r->buffer + 8, xfer->actual_length);
|
memcpy(r->cbuf, r->buffer + 8, xfer->actual_length);
|
||||||
|
|
||||||
/* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices
|
/* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices
|
||||||
@ -394,6 +397,21 @@ static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
|
|||||||
r->cbuf[7] == 9) {
|
r->cbuf[7] == 9) {
|
||||||
r->cbuf[7] = 64;
|
r->cbuf[7] = 64;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
*If this is GET_DESCRIPTOR request for configuration descriptor,
|
||||||
|
* remove 'remote wakeup' flag from it to prevent idle power down
|
||||||
|
* in Windows guest
|
||||||
|
*/
|
||||||
|
if (s->suppress_remote_wake &&
|
||||||
|
udev->setup_buf[0] == USB_DIR_IN &&
|
||||||
|
udev->setup_buf[1] == USB_REQ_GET_DESCRIPTOR &&
|
||||||
|
udev->setup_buf[3] == USB_DT_CONFIG && udev->setup_buf[2] == 0 &&
|
||||||
|
xfer->actual_length >
|
||||||
|
offsetof(struct libusb_config_descriptor, bmAttributes) &&
|
||||||
|
(conf->bmAttributes & USB_CFG_ATT_WAKEUP)) {
|
||||||
|
trace_usb_host_remote_wakeup_removed(s->bus_num, s->addr);
|
||||||
|
conf->bmAttributes &= ~USB_CFG_ATT_WAKEUP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trace_usb_host_req_complete(s->bus_num, s->addr, r->p,
|
trace_usb_host_req_complete(s->bus_num, s->addr, r->p,
|
||||||
r->p->status, r->p->actual_length);
|
r->p->status, r->p->actual_length);
|
||||||
@ -1596,6 +1614,8 @@ static Property usb_host_dev_properties[] = {
|
|||||||
LIBUSB_LOG_LEVEL_WARNING),
|
LIBUSB_LOG_LEVEL_WARNING),
|
||||||
DEFINE_PROP_BIT("pipeline", USBHostDevice, options,
|
DEFINE_PROP_BIT("pipeline", USBHostDevice, options,
|
||||||
USB_HOST_OPT_PIPELINE, true),
|
USB_HOST_OPT_PIPELINE, true),
|
||||||
|
DEFINE_PROP_BOOL("suppress-remote-wake", USBHostDevice,
|
||||||
|
suppress_remote_wake, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,6 +113,8 @@ struct USBRedirDevice {
|
|||||||
/* Properties */
|
/* Properties */
|
||||||
CharBackend cs;
|
CharBackend cs;
|
||||||
bool enable_streams;
|
bool enable_streams;
|
||||||
|
bool suppress_remote_wake;
|
||||||
|
bool in_write;
|
||||||
uint8_t debug;
|
uint8_t debug;
|
||||||
int32_t bootindex;
|
int32_t bootindex;
|
||||||
char *filter_str;
|
char *filter_str;
|
||||||
@ -290,6 +292,13 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Recursion check */
|
||||||
|
if (dev->in_write) {
|
||||||
|
DPRINTF("usbredir_write recursion\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dev->in_write = true;
|
||||||
|
|
||||||
r = qemu_chr_fe_write(&dev->cs, data, count);
|
r = qemu_chr_fe_write(&dev->cs, data, count);
|
||||||
if (r < count) {
|
if (r < count) {
|
||||||
if (!dev->watch) {
|
if (!dev->watch) {
|
||||||
@ -300,6 +309,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
|
|||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dev->in_write = false;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1994,6 +2004,23 @@ static void usbredir_control_packet(void *priv, uint64_t id,
|
|||||||
memcpy(dev->dev.data_buf, data, data_len);
|
memcpy(dev->dev.data_buf, data, data_len);
|
||||||
}
|
}
|
||||||
p->actual_length = len;
|
p->actual_length = len;
|
||||||
|
/*
|
||||||
|
* If this is GET_DESCRIPTOR request for configuration descriptor,
|
||||||
|
* remove 'remote wakeup' flag from it to prevent idle power down
|
||||||
|
* in Windows guest
|
||||||
|
*/
|
||||||
|
if (dev->suppress_remote_wake &&
|
||||||
|
control_packet->requesttype == USB_DIR_IN &&
|
||||||
|
control_packet->request == USB_REQ_GET_DESCRIPTOR &&
|
||||||
|
control_packet->value == (USB_DT_CONFIG << 8) &&
|
||||||
|
control_packet->index == 0 &&
|
||||||
|
/* bmAttributes field of config descriptor */
|
||||||
|
len > 7 && (dev->dev.data_buf[7] & USB_CFG_ATT_WAKEUP)) {
|
||||||
|
DPRINTF("Removed remote wake %04X:%04X\n",
|
||||||
|
dev->device_info.vendor_id,
|
||||||
|
dev->device_info.product_id);
|
||||||
|
dev->dev.data_buf[7] &= ~USB_CFG_ATT_WAKEUP;
|
||||||
|
}
|
||||||
usb_generic_async_ctrl_complete(&dev->dev, p);
|
usb_generic_async_ctrl_complete(&dev->dev, p);
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
@ -2535,6 +2562,8 @@ static Property usbredir_properties[] = {
|
|||||||
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
|
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
|
||||||
DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
||||||
DEFINE_PROP_BOOL("streams", USBRedirDevice, enable_streams, true),
|
DEFINE_PROP_BOOL("streams", USBRedirDevice, enable_streams, true),
|
||||||
|
DEFINE_PROP_BOOL("suppress-remote-wake", USBRedirDevice,
|
||||||
|
suppress_remote_wake, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -266,3 +266,4 @@ usb_host_parse_config(int bus, int addr, int value, int active) "dev %d:%d, valu
|
|||||||
usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d"
|
usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d"
|
||||||
usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d"
|
usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d"
|
||||||
usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s"
|
usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s"
|
||||||
|
usb_host_remote_wakeup_removed(int bus, int addr) "dev %d:%d"
|
||||||
|
Loading…
Reference in New Issue
Block a user