usb: unique packet ids

This patch adds IDs to usb packets.  Those IDs are (a) supposed to be
unique for the lifecycle of a packet (from packet setup until the packet
is either completed or canceled) and (b) stable across migration.

uhci, ohci, ehci and xhci use the guest physical address of the transfer
descriptor for this.

musb needs a different approach because there is no transfer descriptor.
But musb also doesn't support pipelining, so we have never more than one
packet per endpoint in flight.  So we go create an ID based on endpoint
and device address.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2012-08-23 13:30:13 +02:00
parent 0132b4b659
commit e983395d30
7 changed files with 16 additions and 12 deletions

View File

@ -332,6 +332,7 @@ typedef enum USBPacketState {
struct USBPacket {
/* Data fields for use by the driver. */
int pid;
uint64_t id;
USBEndpoint *ep;
QEMUIOVector iov;
uint64_t parameter; /* control transfers */
@ -344,7 +345,7 @@ struct USBPacket {
void usb_packet_init(USBPacket *p);
void usb_packet_set_state(USBPacket *p, USBPacketState state);
void usb_packet_check_state(USBPacket *p, USBPacketState expected);
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id);
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl);

View File

@ -520,10 +520,11 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state)
p->state = state;
}
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id)
{
assert(!usb_packet_is_inflight(p));
assert(p->iov.iov != NULL);
p->id = id;
p->pid = pid;
p->ep = ep;
p->result = 0;

View File

@ -1530,7 +1530,7 @@ static int ehci_execute(EHCIPacket *p, const char *action)
endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
ep = usb_ep_get(p->queue->dev, p->pid, endp);
usb_packet_setup(&p->packet, p->pid, ep);
usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr);
usb_packet_map(&p->packet, &p->sgl);
trace_usb_ehci_packet_action(p->queue, p, action);
@ -1552,7 +1552,8 @@ static int ehci_execute(EHCIPacket *p, const char *action)
*/
static int ehci_process_itd(EHCIState *ehci,
EHCIitd *itd)
EHCIitd *itd,
uint32_t addr)
{
USBDevice *dev;
USBEndpoint *ep;
@ -1598,7 +1599,7 @@ static int ehci_process_itd(EHCIState *ehci,
dev = ehci_find_device(ehci, devaddr);
ep = usb_ep_get(dev, pid, endp);
if (ep->type == USB_ENDPOINT_XFER_ISOC) {
usb_packet_setup(&ehci->ipacket, pid, ep);
usb_packet_setup(&ehci->ipacket, pid, ep, addr);
usb_packet_map(&ehci->ipacket, &ehci->isgl);
ret = usb_handle_packet(dev, &ehci->ipacket);
assert(ret != USB_RET_ASYNC);
@ -1862,7 +1863,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
sizeof(EHCIitd) >> 2);
ehci_trace_itd(ehci, entry, &itd);
if (ehci_process_itd(ehci, &itd) != 0) {
if (ehci_process_itd(ehci, &itd, entry) != 0) {
return -1;
}

View File

@ -626,7 +626,8 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
/* A wild guess on the FADDR semantics... */
dev = usb_find_device(&s->port, ep->faddr[idx]);
uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
usb_packet_setup(&ep->packey[dir].p, pid, uep);
usb_packet_setup(&ep->packey[dir].p, pid, uep,
(dev->addr << 16) | (uep->nr << 8) | pid);
usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
ep->packey[dir].ep = ep;
ep->packey[dir].dir = dir;

View File

@ -812,7 +812,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
} else {
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep);
usb_packet_setup(&ohci->usb_packet, pid, ep, addr);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
ret = usb_handle_packet(dev, &ohci->usb_packet);
if (ret == USB_RET_ASYNC) {
@ -1011,7 +1011,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
}
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep);
usb_packet_setup(&ohci->usb_packet, pid, ep, addr);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
ret = usb_handle_packet(dev, &ohci->usb_packet);
#ifdef DEBUG_PACKET

View File

@ -859,14 +859,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
* for initial isochronous requests
*/
async->queue->valid = 32;
async->isoc = td->ctrl & TD_CTRL_IOS;
async->isoc = td->ctrl & TD_CTRL_IOS;
max_len = ((td->token >> 21) + 1) & 0x7ff;
pid = td->token & 0xff;
dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
usb_packet_setup(&async->packet, pid, ep);
usb_packet_setup(&async->packet, pid, ep, addr);
qemu_sglist_add(&async->sgl, td->buffer, max_len);
usb_packet_map(&async->packet, &async->sgl);

View File

@ -1392,7 +1392,7 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
ep = usb_ep_get(dev, dir, xfer->epid >> 1);
usb_packet_setup(&xfer->packet, dir, ep);
usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr);
usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
xfer->packet.pid, dev->addr, ep->nr);