Merge remote-tracking branch 'kraxel/usb.88' into staging
# By Gerd Hoffmann (10) and Marcel Apfelbaum (1) # Via Gerd Hoffmann * kraxel/usb.88: usb/dev-hid: Modified usb-tablet category from Misc to Input Revert "usb-hub: report status changes only once" usb-hub: add tracepoint for status reports usb: parallelize usb3 streams uas: add property for request logging xhci: reset port when disabling slot xhci: emulate intr endpoint intervals correctly xhci: fix endpoint interval calculation xhci: add port to slot_address tracepoint xhci: add tracepoint for endpoint state changes xhci: remove leftover debug printf Message-id: 1378117055-29620-1-git-send-email-kraxel@redhat.com Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
commit
9ea0f58fc7
@ -403,7 +403,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
|
||||
p->ep->halted = false;
|
||||
}
|
||||
|
||||
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
|
||||
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline || p->stream) {
|
||||
usb_process_one(p);
|
||||
if (p->status == USB_RET_ASYNC) {
|
||||
/* hcd drivers cannot handle async for isoc */
|
||||
@ -420,7 +420,8 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
|
||||
* When pipelining is enabled usb-devices must always return async,
|
||||
* otherwise packets can complete out of order!
|
||||
*/
|
||||
assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
|
||||
assert(p->stream || !p->ep->pipeline ||
|
||||
QTAILQ_EMPTY(&p->ep->queue));
|
||||
if (p->status != USB_RET_NAK) {
|
||||
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
||||
}
|
||||
@ -434,7 +435,7 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
|
||||
{
|
||||
USBEndpoint *ep = p->ep;
|
||||
|
||||
assert(QTAILQ_FIRST(&ep->queue) == p);
|
||||
assert(p->stream || QTAILQ_FIRST(&ep->queue) == p);
|
||||
assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK);
|
||||
|
||||
if (p->status != USB_RET_SUCCESS ||
|
||||
|
@ -658,7 +658,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
|
||||
uc->product_desc = "QEMU USB Tablet";
|
||||
dc->vmsd = &vmstate_usb_ptr;
|
||||
dc->props = usb_tablet_properties;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo usb_tablet_info = {
|
||||
|
@ -33,7 +33,6 @@ typedef struct USBHubPort {
|
||||
USBPort port;
|
||||
uint16_t wPortStatus;
|
||||
uint16_t wPortChange;
|
||||
uint16_t wPortChange_reported;
|
||||
} USBHubPort;
|
||||
|
||||
typedef struct USBHubState {
|
||||
@ -468,13 +467,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p)
|
||||
status = 0;
|
||||
for(i = 0; i < NUM_PORTS; i++) {
|
||||
port = &s->ports[i];
|
||||
if (port->wPortChange &&
|
||||
port->wPortChange_reported != port->wPortChange) {
|
||||
if (port->wPortChange)
|
||||
status |= (1 << (i + 1));
|
||||
}
|
||||
port->wPortChange_reported = port->wPortChange;
|
||||
}
|
||||
if (status != 0) {
|
||||
trace_usb_hub_status_report(s->dev.addr, status);
|
||||
for(i = 0; i < n; i++) {
|
||||
buf[i] = status >> (8 * i);
|
||||
}
|
||||
|
@ -113,6 +113,9 @@ struct UASDevice {
|
||||
QTAILQ_HEAD(, UASStatus) results;
|
||||
QTAILQ_HEAD(, UASRequest) requests;
|
||||
|
||||
/* properties */
|
||||
uint32_t requestlog;
|
||||
|
||||
/* usb 2.0 only */
|
||||
USBPacket *status2;
|
||||
UASRequest *datain2;
|
||||
@ -692,9 +695,9 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui)
|
||||
req->req = scsi_req_new(req->dev, req->tag,
|
||||
usb_uas_get_lun(req->lun),
|
||||
ui->command.cdb, req);
|
||||
#if 1
|
||||
if (uas->requestlog) {
|
||||
scsi_req_print(req->req);
|
||||
#endif
|
||||
}
|
||||
len = scsi_req_enqueue(req->req);
|
||||
if (len) {
|
||||
req->data_size = len;
|
||||
@ -903,6 +906,11 @@ static const VMStateDescription vmstate_usb_uas = {
|
||||
}
|
||||
};
|
||||
|
||||
static Property uas_properties[] = {
|
||||
DEFINE_PROP_UINT32("log-scsi-req", UASDevice, requestlog, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void usb_uas_class_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@ -920,6 +928,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
dc->fw_name = "storage";
|
||||
dc->vmsd = &vmstate_usb_uas;
|
||||
dc->props = uas_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo uas_info = {
|
||||
|
@ -355,6 +355,7 @@ typedef struct XHCITransfer {
|
||||
unsigned int streamid;
|
||||
bool in_xfer;
|
||||
bool iso_xfer;
|
||||
bool timed_xfer;
|
||||
|
||||
unsigned int trb_count;
|
||||
unsigned int trb_alloced;
|
||||
@ -586,6 +587,14 @@ static const char *TRBCCode_names[] = {
|
||||
[CC_SPLIT_TRANSACTION_ERROR] = "CC_SPLIT_TRANSACTION_ERROR",
|
||||
};
|
||||
|
||||
static const char *ep_state_names[] = {
|
||||
[EP_DISABLED] = "disabled",
|
||||
[EP_RUNNING] = "running",
|
||||
[EP_HALTED] = "halted",
|
||||
[EP_STOPPED] = "stopped",
|
||||
[EP_ERROR] = "error",
|
||||
};
|
||||
|
||||
static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
|
||||
{
|
||||
if (index >= llen || list[index] == NULL) {
|
||||
@ -606,6 +615,12 @@ static const char *event_name(XHCIEvent *event)
|
||||
ARRAY_SIZE(TRBCCode_names));
|
||||
}
|
||||
|
||||
static const char *ep_state_name(uint32_t state)
|
||||
{
|
||||
return lookup_name(state, ep_state_names,
|
||||
ARRAY_SIZE(ep_state_names));
|
||||
}
|
||||
|
||||
static uint64_t xhci_mfindex_get(XHCIState *xhci)
|
||||
{
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
@ -1164,8 +1179,6 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
|
||||
|
||||
if (sctx->sct == -1) {
|
||||
xhci_dma_read_u32s(epctx->xhci, sctx->pctx, ctx, sizeof(ctx));
|
||||
fprintf(stderr, "%s: init sctx #%d @ " DMA_ADDR_FMT ": %08x %08x\n",
|
||||
__func__, streamid, sctx->pctx, ctx[0], ctx[1]);
|
||||
sct = (ctx[0] >> 1) & 0x07;
|
||||
if (epctx->lsa && sct != 1) {
|
||||
*cc_error = CC_INVALID_STREAM_TYPE_ERROR;
|
||||
@ -1205,6 +1218,11 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
|
||||
}
|
||||
|
||||
xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
|
||||
if (epctx->state != state) {
|
||||
trace_usb_xhci_ep_state(epctx->slotid, epctx->epid,
|
||||
ep_state_name(epctx->state),
|
||||
ep_state_name(state));
|
||||
}
|
||||
epctx->state = state;
|
||||
}
|
||||
|
||||
@ -1257,7 +1275,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx,
|
||||
epctx->ring.ccs = ctx[2] & 1;
|
||||
}
|
||||
|
||||
epctx->interval = 1 << (ctx[0] >> 16) & 0xff;
|
||||
epctx->interval = 1 << ((ctx[0] >> 16) & 0xff);
|
||||
}
|
||||
|
||||
static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
|
||||
@ -1803,6 +1821,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
|
||||
|
||||
xfer->in_xfer = bmRequestType & USB_DIR_IN;
|
||||
xfer->iso_xfer = false;
|
||||
xfer->timed_xfer = false;
|
||||
|
||||
if (xhci_setup_packet(xfer) < 0) {
|
||||
return -1;
|
||||
@ -1818,6 +1837,17 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer,
|
||||
XHCIEPContext *epctx, uint64_t mfindex)
|
||||
{
|
||||
uint64_t asap = ((mfindex + epctx->interval - 1) &
|
||||
~(epctx->interval-1));
|
||||
uint64_t kick = epctx->mfindex_last + epctx->interval;
|
||||
|
||||
assert(epctx->interval != 0);
|
||||
xfer->mfindex_kick = MAX(asap, kick);
|
||||
}
|
||||
|
||||
static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
|
||||
XHCIEPContext *epctx, uint64_t mfindex)
|
||||
{
|
||||
@ -1840,7 +1870,7 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
|
||||
}
|
||||
}
|
||||
|
||||
static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
|
||||
static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
|
||||
XHCIEPContext *epctx, uint64_t mfindex)
|
||||
{
|
||||
if (xfer->mfindex_kick > mfindex) {
|
||||
@ -1866,18 +1896,30 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
|
||||
switch(epctx->type) {
|
||||
case ET_INTR_OUT:
|
||||
case ET_INTR_IN:
|
||||
xfer->pkts = 0;
|
||||
xfer->iso_xfer = false;
|
||||
xfer->timed_xfer = true;
|
||||
mfindex = xhci_mfindex_get(xhci);
|
||||
xhci_calc_intr_kick(xhci, xfer, epctx, mfindex);
|
||||
xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
if (xfer->running_retry) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case ET_BULK_OUT:
|
||||
case ET_BULK_IN:
|
||||
xfer->pkts = 0;
|
||||
xfer->iso_xfer = false;
|
||||
xfer->timed_xfer = false;
|
||||
break;
|
||||
case ET_ISO_OUT:
|
||||
case ET_ISO_IN:
|
||||
xfer->pkts = 1;
|
||||
xfer->iso_xfer = true;
|
||||
xfer->timed_xfer = true;
|
||||
mfindex = xhci_mfindex_get(xhci);
|
||||
xhci_calc_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
if (xfer->running_retry) {
|
||||
return -1;
|
||||
}
|
||||
@ -1938,13 +1980,18 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
|
||||
|
||||
trace_usb_xhci_xfer_retry(xfer);
|
||||
assert(xfer->running_retry);
|
||||
if (xfer->iso_xfer) {
|
||||
/* retry delayed iso transfer */
|
||||
if (xfer->timed_xfer) {
|
||||
/* time to kick the transfer? */
|
||||
mfindex = xhci_mfindex_get(xhci);
|
||||
xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
|
||||
if (xfer->running_retry) {
|
||||
return;
|
||||
}
|
||||
xfer->timed_xfer = 0;
|
||||
xfer->running_retry = 1;
|
||||
}
|
||||
if (xfer->iso_xfer) {
|
||||
/* retry iso transfer */
|
||||
if (xhci_setup_packet(xfer) < 0) {
|
||||
return;
|
||||
}
|
||||
@ -2030,7 +2077,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
|
||||
epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
|
||||
ep = xfer->packet.ep;
|
||||
} else {
|
||||
if (!xfer->iso_xfer) {
|
||||
if (!xfer->timed_xfer) {
|
||||
fprintf(stderr, "xhci: error firing data transfer\n");
|
||||
}
|
||||
}
|
||||
@ -2076,6 +2123,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
|
||||
|
||||
xhci->slots[slotid-1].enabled = 0;
|
||||
xhci->slots[slotid-1].addressed = 0;
|
||||
xhci->slots[slotid-1].uport = NULL;
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2118,7 +2166,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
|
||||
int i;
|
||||
TRBCCode res;
|
||||
|
||||
trace_usb_xhci_slot_address(slotid);
|
||||
assert(slotid >= 1 && slotid <= xhci->numslots);
|
||||
|
||||
dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
|
||||
@ -2151,6 +2198,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
|
||||
fprintf(stderr, "xhci: port not found\n");
|
||||
return CC_TRB_ERROR;
|
||||
}
|
||||
trace_usb_xhci_slot_address(slotid, uport->path);
|
||||
|
||||
dev = uport->dev;
|
||||
if (!dev) {
|
||||
|
@ -371,7 +371,7 @@ usb_xhci_port_link(uint32_t port, uint32_t pls) "port %d, pls %d"
|
||||
usb_xhci_port_notify(uint32_t port, uint32_t pls) "port %d, bits %x"
|
||||
usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
|
||||
usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
|
||||
usb_xhci_slot_address(uint32_t slotid) "slotid %d"
|
||||
usb_xhci_slot_address(uint32_t slotid, const char *port) "slotid %d, port %s"
|
||||
usb_xhci_slot_configure(uint32_t slotid) "slotid %d"
|
||||
usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d"
|
||||
usb_xhci_slot_reset(uint32_t slotid) "slotid %d"
|
||||
@ -381,6 +381,7 @@ usb_xhci_ep_set_dequeue(uint32_t slotid, uint32_t epid, uint32_t streamid, uint6
|
||||
usb_xhci_ep_kick(uint32_t slotid, uint32_t epid, uint32_t streamid) "slotid %d, epid %d, streamid %d"
|
||||
usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
|
||||
usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
|
||||
usb_xhci_ep_state(uint32_t slotid, uint32_t epid, const char *os, const char *ns) "slotid %d, epid %d, %s -> %s"
|
||||
usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t streamid) "%p: slotid %d, epid %d, streamid %d"
|
||||
usb_xhci_xfer_async(void *xfer) "%p"
|
||||
usb_xhci_xfer_nak(void *xfer) "%p"
|
||||
@ -410,6 +411,7 @@ usb_hub_set_port_feature(int addr, int nr, const char *f) "dev %d, port %d, feat
|
||||
usb_hub_clear_port_feature(int addr, int nr, const char *f) "dev %d, port %d, feature %s"
|
||||
usb_hub_attach(int addr, int nr) "dev %d, port %d"
|
||||
usb_hub_detach(int addr, int nr) "dev %d, port %d"
|
||||
usb_hub_status_report(int addr, int status) "dev %d, status 0x%x"
|
||||
|
||||
# hw/usb/dev-uas.c
|
||||
usb_uas_reset(int addr) "dev %d"
|
||||
|
Loading…
Reference in New Issue
Block a user