mirror of https://gitee.com/openkylin/qemu.git
ehci: cache USBDevice in EHCIQueue
Keep a USBDevice pointer in EHCIQueue so we don't have to lookup the device on each usb packet submission. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
4224558f87
commit
e59928b3d1
|
@ -371,6 +371,7 @@ struct EHCIQueue {
|
||||||
EHCIqh qh; /* copy of current QH (being worked on) */
|
EHCIqh qh; /* copy of current QH (being worked on) */
|
||||||
uint32_t qhaddr; /* address QH read from */
|
uint32_t qhaddr; /* address QH read from */
|
||||||
uint32_t qtdaddr; /* address QTD read from */
|
uint32_t qtdaddr; /* address QTD read from */
|
||||||
|
USBDevice *dev;
|
||||||
QTAILQ_HEAD(, EHCIPacket) packets;
|
QTAILQ_HEAD(, EHCIPacket) packets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -758,11 +759,9 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
|
||||||
{
|
{
|
||||||
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||||
EHCIQueue *q, *tmp;
|
EHCIQueue *q, *tmp;
|
||||||
int addr;
|
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
||||||
addr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
|
if (q->dev != dev) {
|
||||||
if (addr != dev->addr) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ehci_free_queue(q, async);
|
ehci_free_queue(q, async);
|
||||||
|
@ -1397,11 +1396,9 @@ static void ehci_execute_complete(EHCIQueue *q)
|
||||||
|
|
||||||
static int ehci_execute(EHCIPacket *p)
|
static int ehci_execute(EHCIPacket *p)
|
||||||
{
|
{
|
||||||
USBDevice *dev;
|
|
||||||
USBEndpoint *ep;
|
USBEndpoint *ep;
|
||||||
int ret;
|
int ret;
|
||||||
int endp;
|
int endp;
|
||||||
int devadr;
|
|
||||||
|
|
||||||
if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
|
if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
|
||||||
fprintf(stderr, "Attempting to execute inactive qtd\n");
|
fprintf(stderr, "Attempting to execute inactive qtd\n");
|
||||||
|
@ -1435,16 +1432,12 @@ static int ehci_execute(EHCIPacket *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
|
endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
|
||||||
devadr = get_field(p->queue->qh.epchar, QH_EPCHAR_DEVADDR);
|
ep = usb_ep_get(p->queue->dev, p->pid, endp);
|
||||||
|
|
||||||
/* TODO: associating device with ehci port */
|
|
||||||
dev = ehci_find_device(p->queue->ehci, devadr);
|
|
||||||
ep = usb_ep_get(dev, p->pid, endp);
|
|
||||||
|
|
||||||
usb_packet_setup(&p->packet, p->pid, ep);
|
usb_packet_setup(&p->packet, p->pid, ep);
|
||||||
usb_packet_map(&p->packet, &p->sgl);
|
usb_packet_map(&p->packet, &p->sgl);
|
||||||
|
|
||||||
ret = usb_handle_packet(dev, &p->packet);
|
ret = usb_handle_packet(p->queue->dev, &p->packet);
|
||||||
DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
|
DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
|
||||||
"(total %d) endp %x ret %d\n",
|
"(total %d) endp %x ret %d\n",
|
||||||
q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
|
q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
|
||||||
|
@ -1658,7 +1651,7 @@ out:
|
||||||
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||||
{
|
{
|
||||||
EHCIPacket *p;
|
EHCIPacket *p;
|
||||||
uint32_t entry;
|
uint32_t entry, devaddr;
|
||||||
EHCIQueue *q;
|
EHCIQueue *q;
|
||||||
|
|
||||||
entry = ehci_get_fetch_addr(ehci, async);
|
entry = ehci_get_fetch_addr(ehci, async);
|
||||||
|
@ -1681,6 +1674,20 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||||
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
|
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
|
||||||
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
|
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
|
||||||
|
|
||||||
|
devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
|
||||||
|
if (q->dev != NULL && q->dev->addr != devaddr) {
|
||||||
|
if (!QTAILQ_EMPTY(&q->packets)) {
|
||||||
|
/* should not happen (guest bug) */
|
||||||
|
while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
|
||||||
|
ehci_free_packet(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q->dev = NULL;
|
||||||
|
}
|
||||||
|
if (q->dev == NULL) {
|
||||||
|
q->dev = ehci_find_device(q->ehci, devaddr);
|
||||||
|
}
|
||||||
|
|
||||||
if (p && p->async == EHCI_ASYNC_INFLIGHT) {
|
if (p && p->async == EHCI_ASYNC_INFLIGHT) {
|
||||||
/* I/O still in progress -- skip queue */
|
/* I/O still in progress -- skip queue */
|
||||||
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
||||||
|
|
Loading…
Reference in New Issue