usb: various bugfixes, mostly xhci.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJYmF1rAAoJEEy22O7T6HE4UQgP/RGWAnt4dJAk3SDzZilYexS7 rol3cNAUuhLI/sV6syh8paFdSiD0+mDw8h0n+QLS+bgP50WmRhu4xJTHpnzWdXfV 7EGvZI2Gnjy2XMccr5q8hfSragI8MJKgUkW/32v9nvTmA+1lnvK2t6PeSjhwD7zf WTsdv7mi3D5LMbCCtTCy7X0ojIHZ009nU9sroz8KEzF752j6NRLiCn7UfRjT+m24 IHYhUX2TLU7dw+TzhnQPzFalaZMj0mGowtP517Ugw3lsXxtxsRStpKmp5Js0+d4N amH/PPmZmaESfrv3OKvcZ6C4VCCgXAWa88nQZt1oST5/oQbskNYR+SS/rHUL4JJ0 Y4Ta0euwQGwCJVyFhOHJPoZM64L+3SzeQJQXNAiiYxy9427y+UZ+VA2ffHpUr3+4 zc6x9Jc43+l0YE9eRlkwv8dr7S3xzWoMqaUJag941VRg0M6F+Ox74r9dnFC9UW+L JIP4wFMGnJflSQsl6KlAaGd+sUnArOcwZHIyp47TauEx4bGoUeVzTbvz8a+VZ+22 rkMdR5JuHbw65fjxfAXgaqxmEA8+eYzyjO4CbWmBdcuZbIhrDRvUcBCTSQaxVg8T nrBesIsHKFTuKywHGHrpli1d9SqO9tOo9nM3voD+mpKXeTLYtJ1/2RX6487JkTob flY8/lupvCLEtzXH3Fyg =gltI -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20170206-1' into staging usb: various bugfixes, mostly xhci. # gpg: Signature made Mon 06 Feb 2017 11:26:35 GMT # gpg: using RSA key 0x4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/pull-usb-20170206-1: xhci: fix event queue IRQ handling usb: ccid: check ccid apdu length xhci: guard xhci_kick_epctx against recursive calls xhci: don't kick in xhci_submit and xhci_fire_ctl_transfer xhci: rename xhci_complete_packet to xhci_try_complete_packet xhci: only free completed transfers usb: accept usb3 control requests usb/uas: more verbose error message hw/usb/dev-hid: Improve guest compatibility of usb-tablet Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7d2c6c9551
@ -774,6 +774,13 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
trace_usb_set_device_feature(dev->addr, value, ret);
|
||||
break;
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_SEL:
|
||||
case DeviceOutRequest | USB_REQ_SET_ISOCH_DELAY:
|
||||
if (dev->speed == USB_SPEED_SUPER) {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE:
|
||||
if (index < 0 || index >= dev->ninterfaces) {
|
||||
break;
|
||||
|
@ -144,7 +144,7 @@ static const USBDescIface desc_iface_tablet = {
|
||||
.bInterfaceNumber = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_HID,
|
||||
.bInterfaceProtocol = 0x02,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.ndesc = 1,
|
||||
.descs = (USBDescOther[]) {
|
||||
{
|
||||
@ -174,7 +174,7 @@ static const USBDescIface desc_iface_tablet2 = {
|
||||
.bInterfaceNumber = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_HID,
|
||||
.bInterfaceProtocol = 0x02,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.ndesc = 1,
|
||||
.descs = (USBDescOther[]) {
|
||||
{
|
||||
@ -487,7 +487,7 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = {
|
||||
|
||||
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
|
||||
0x05, 0x01, /* Usage Page (Generic Desktop) */
|
||||
0x09, 0x01, /* Usage (Pointer) */
|
||||
0x09, 0x02, /* Usage (Mouse) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
0x09, 0x01, /* Usage (Pointer) */
|
||||
0xa1, 0x00, /* Collection (Physical) */
|
||||
|
@ -967,7 +967,7 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
|
||||
DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
|
||||
recv->hdr.bSeq, len);
|
||||
ccid_add_pending_answer(s, (CCID_Header *)recv);
|
||||
if (s->card) {
|
||||
if (s->card && len <= BULK_OUT_DATA_SIZE) {
|
||||
ccid_card_apdu_from_guest(s->card, recv->abData, len);
|
||||
} else {
|
||||
DPRINTF(s, D_WARN, "warning: discarded apdu\n");
|
||||
|
@ -653,7 +653,8 @@ static void usb_uas_handle_control(USBDevice *dev, USBPacket *p,
|
||||
if (ret >= 0) {
|
||||
return;
|
||||
}
|
||||
error_report("%s: unhandled control request", __func__);
|
||||
error_report("%s: unhandled control request (req 0x%x, val 0x%x, idx 0x%x",
|
||||
__func__, request, value, index);
|
||||
p->status = USB_RET_STALL;
|
||||
}
|
||||
|
||||
|
@ -390,6 +390,7 @@ struct XHCIEPContext {
|
||||
dma_addr_t pctx;
|
||||
unsigned int max_psize;
|
||||
uint32_t state;
|
||||
uint32_t kick_active;
|
||||
|
||||
/* streams */
|
||||
unsigned int max_pstreams;
|
||||
@ -788,11 +789,15 @@ static void xhci_msix_update(XHCIState *xhci, int v)
|
||||
static void xhci_intr_raise(XHCIState *xhci, int v)
|
||||
{
|
||||
PCIDevice *pci_dev = PCI_DEVICE(xhci);
|
||||
bool pending = (xhci->intr[v].erdp_low & ERDP_EHB);
|
||||
|
||||
xhci->intr[v].erdp_low |= ERDP_EHB;
|
||||
xhci->intr[v].iman |= IMAN_IP;
|
||||
xhci->usbsts |= USBSTS_EINT;
|
||||
|
||||
if (pending) {
|
||||
return;
|
||||
}
|
||||
if (!(xhci->intr[v].iman & IMAN_IE)) {
|
||||
return;
|
||||
}
|
||||
@ -1897,7 +1902,7 @@ static int xhci_setup_packet(XHCITransfer *xfer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xhci_complete_packet(XHCITransfer *xfer)
|
||||
static int xhci_try_complete_packet(XHCITransfer *xfer)
|
||||
{
|
||||
if (xfer->packet.status == USB_RET_ASYNC) {
|
||||
trace_usb_xhci_xfer_async(xfer);
|
||||
@ -2001,11 +2006,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
|
||||
xfer->packet.parameter = trb_setup->parameter;
|
||||
|
||||
usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
|
||||
|
||||
xhci_complete_packet(xfer);
|
||||
if (!xfer->running_async && !xfer->running_retry) {
|
||||
xhci_kick_epctx(xfer->epctx, 0);
|
||||
}
|
||||
xhci_try_complete_packet(xfer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2105,11 +2106,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
|
||||
return -1;
|
||||
}
|
||||
usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
|
||||
|
||||
xhci_complete_packet(xfer);
|
||||
if (!xfer->running_async && !xfer->running_retry) {
|
||||
xhci_kick_epctx(xfer->epctx, xfer->streamid);
|
||||
}
|
||||
xhci_try_complete_packet(xfer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2139,6 +2136,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
|
||||
return;
|
||||
}
|
||||
|
||||
if (epctx->kick_active) {
|
||||
return;
|
||||
}
|
||||
xhci_kick_epctx(epctx, streamid);
|
||||
}
|
||||
|
||||
@ -2154,6 +2154,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
int i;
|
||||
|
||||
trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);
|
||||
assert(!epctx->kick_active);
|
||||
|
||||
/* 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 */
|
||||
@ -2185,7 +2186,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
}
|
||||
usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
|
||||
assert(xfer->packet.status != USB_RET_NAK);
|
||||
xhci_complete_packet(xfer);
|
||||
xhci_try_complete_packet(xfer);
|
||||
} else {
|
||||
/* retry nak'ed transfer */
|
||||
if (xhci_setup_packet(xfer) < 0) {
|
||||
@ -2195,10 +2196,12 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
if (xfer->packet.status == USB_RET_NAK) {
|
||||
return;
|
||||
}
|
||||
xhci_complete_packet(xfer);
|
||||
xhci_try_complete_packet(xfer);
|
||||
}
|
||||
assert(!xfer->running_retry);
|
||||
xhci_ep_free_xfer(epctx->retry);
|
||||
if (xfer->complete) {
|
||||
xhci_ep_free_xfer(epctx->retry);
|
||||
}
|
||||
epctx->retry = NULL;
|
||||
}
|
||||
|
||||
@ -2223,6 +2226,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
}
|
||||
assert(ring->dequeue != 0);
|
||||
|
||||
epctx->kick_active++;
|
||||
while (1) {
|
||||
length = xhci_ring_chain_length(xhci, ring);
|
||||
if (length <= 0) {
|
||||
@ -2259,6 +2263,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
epctx->kick_active--;
|
||||
|
||||
ep = xhci_epid_to_usbep(epctx);
|
||||
if (ep) {
|
||||
@ -3351,6 +3356,15 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
|
||||
intr->erdp_low &= ~ERDP_EHB;
|
||||
}
|
||||
intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB);
|
||||
if (val & ERDP_EHB) {
|
||||
dma_addr_t erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
|
||||
unsigned int dp_idx = (erdp - intr->er_start) / TRB_SIZE;
|
||||
if (erdp >= intr->er_start &&
|
||||
erdp < (intr->er_start + TRB_SIZE * intr->er_size) &&
|
||||
dp_idx != intr->er_ep_idx) {
|
||||
xhci_intr_raise(xhci, v);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1c: /* ERDP high */
|
||||
intr->erdp_high = val;
|
||||
@ -3490,7 +3504,7 @@ static void xhci_complete(USBPort *port, USBPacket *packet)
|
||||
xhci_ep_nuke_one_xfer(xfer, 0);
|
||||
return;
|
||||
}
|
||||
xhci_complete_packet(xfer);
|
||||
xhci_try_complete_packet(xfer);
|
||||
xhci_kick_epctx(xfer->epctx, xfer->streamid);
|
||||
if (xfer->complete) {
|
||||
xhci_ep_free_xfer(xfer);
|
||||
|
@ -135,6 +135,8 @@
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
#define USB_REQ_SET_SEL 0x30
|
||||
#define USB_REQ_SET_ISOCH_DELAY 0x31
|
||||
|
||||
#define USB_DEVICE_SELF_POWERED 0
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1
|
||||
|
Loading…
Reference in New Issue
Block a user