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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user