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:
Anthony Liguori 2013-09-03 12:31:30 -05:00
commit 9ea0f58fc7
6 changed files with 81 additions and 24 deletions

View File

@ -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 ||

View File

@ -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 = {

View File

@ -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);
}

View File

@ -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
scsi_req_print(req->req);
#endif
if (uas->requestlog) {
scsi_req_print(req->req);
}
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 = {

View File

@ -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,8 +1870,8 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
}
}
static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
XHCIEPContext *epctx, uint64_t mfindex)
static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
XHCIEPContext *epctx, uint64_t mfindex)
{
if (xfer->mfindex_kick > mfindex) {
timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
@ -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) {

View File

@ -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"