usb: USBPacket: add status, rename owner -> ep
Add enum to track the status of USBPackets, use that instead of the owner pointer to figure whenever a usb packet is currently in flight or not. Add some more packet status sanity checks. Also rename the USBEndpoint pointer from "owner" to "ep". Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
		
							parent
							
								
									1977f93dac
								
							
						
					
					
						commit
						f53c398aa6
					
				| @ -715,8 +715,8 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev) | ||||
|     EHCIQueue *q, *tmp; | ||||
| 
 | ||||
|     QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) { | ||||
|         if (q->packet.owner == NULL || | ||||
|             q->packet.owner->dev != dev) { | ||||
|         if (!usb_packet_is_inflight(&q->packet) || | ||||
|             q->packet.ep->dev != dev) { | ||||
|             continue; | ||||
|         } | ||||
|         ehci_free_queue(q); | ||||
|  | ||||
| @ -811,8 +811,8 @@ static void musb_async_cancel_device(MUSBState *s, USBDevice *dev) | ||||
| 
 | ||||
|     for (ep = 0; ep < 16; ep++) { | ||||
|         for (dir = 0; dir < 2; dir++) { | ||||
|             if (s->ep[ep].packey[dir].p.owner == NULL || | ||||
|                 s->ep[ep].packey[dir].p.owner->dev != dev) { | ||||
|             if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) || | ||||
|                 s->ep[ep].packey[dir].p.ep->dev != dev) { | ||||
|                 continue; | ||||
|             } | ||||
|             usb_cancel_packet(&s->ep[ep].packey[dir].p); | ||||
|  | ||||
| @ -1709,8 +1709,8 @@ static void ohci_mem_write(void *opaque, | ||||
| static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev) | ||||
| { | ||||
|     if (ohci->async_td && | ||||
|         ohci->usb_packet.owner != NULL && | ||||
|         ohci->usb_packet.owner->dev == dev) { | ||||
|         usb_packet_is_inflight(&ohci->usb_packet) && | ||||
|         ohci->usb_packet.ep->dev == dev) { | ||||
|         usb_cancel_packet(&ohci->usb_packet); | ||||
|         ohci->async_td = 0; | ||||
|     } | ||||
|  | ||||
| @ -236,8 +236,8 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev) | ||||
|     UHCIAsync *curr, *n; | ||||
| 
 | ||||
|     QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) { | ||||
|         if (curr->packet.owner == NULL || | ||||
|             curr->packet.owner->dev != dev) { | ||||
|         if (!usb_packet_is_inflight(&curr->packet) || | ||||
|             curr->packet.ep->dev != dev) { | ||||
|             continue; | ||||
|         } | ||||
|         uhci_async_unlink(s, curr); | ||||
|  | ||||
							
								
								
									
										18
									
								
								hw/usb.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								hw/usb.c
									
									
									
									
									
								
							| @ -291,7 +291,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) | ||||
|     } | ||||
|     assert(dev->addr == p->devaddr); | ||||
|     assert(dev->state == USB_STATE_DEFAULT); | ||||
|     assert(p->owner == NULL); | ||||
|     assert(p->state == USB_PACKET_SETUP); | ||||
| 
 | ||||
|     if (p->devep == 0) { | ||||
|         /* control pipe */ | ||||
| @ -315,7 +315,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) | ||||
|     } | ||||
| 
 | ||||
|     if (ret == USB_RET_ASYNC) { | ||||
|         p->owner = usb_ep_get(dev, p->pid, p->devep); | ||||
|         p->ep = usb_ep_get(dev, p->pid, p->devep); | ||||
|         p->state = USB_PACKET_ASYNC; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| @ -325,8 +326,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) | ||||
|    handle_packet. */ | ||||
| void usb_packet_complete(USBDevice *dev, USBPacket *p) | ||||
| { | ||||
|     assert(p->owner != NULL); | ||||
|     p->owner = NULL; | ||||
|     assert(p->state == USB_PACKET_ASYNC); | ||||
|     p->state = USB_PACKET_COMPLETE; | ||||
|     dev->port->ops->complete(dev->port, p); | ||||
| } | ||||
| 
 | ||||
| @ -335,9 +336,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) | ||||
|    completed.  */ | ||||
| void usb_cancel_packet(USBPacket * p) | ||||
| { | ||||
|     assert(p->owner != NULL); | ||||
|     usb_device_cancel_packet(p->owner->dev, p); | ||||
|     p->owner = NULL; | ||||
|     assert(p->state == USB_PACKET_ASYNC); | ||||
|     p->state = USB_PACKET_CANCELED; | ||||
|     usb_device_cancel_packet(p->ep->dev, p); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -348,6 +349,8 @@ void usb_packet_init(USBPacket *p) | ||||
| 
 | ||||
| void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep) | ||||
| { | ||||
|     assert(!usb_packet_is_inflight(p)); | ||||
|     p->state = USB_PACKET_SETUP; | ||||
|     p->pid = pid; | ||||
|     p->devaddr = addr; | ||||
|     p->devep = ep; | ||||
| @ -391,6 +394,7 @@ void usb_packet_skip(USBPacket *p, size_t bytes) | ||||
| 
 | ||||
| void usb_packet_cleanup(USBPacket *p) | ||||
| { | ||||
|     assert(!usb_packet_is_inflight(p)); | ||||
|     qemu_iovec_destroy(&p->iov); | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										19
									
								
								hw/usb.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								hw/usb.h
									
									
									
									
									
								
							| @ -289,8 +289,7 @@ typedef struct USBPortOps { | ||||
|     void (*wakeup)(USBPort *port); | ||||
|     /*
 | ||||
|      * Note that port->dev will be different then the device from which | ||||
|      * the packet originated when a hub is involved, if you want the orginating | ||||
|      * device use p->owner | ||||
|      * the packet originated when a hub is involved. | ||||
|      */ | ||||
|     void (*complete)(USBPort *port, USBPacket *p); | ||||
| } USBPortOps; | ||||
| @ -309,15 +308,24 @@ struct USBPort { | ||||
| typedef void USBCallback(USBPacket * packet, void *opaque); | ||||
| 
 | ||||
| /* Structure used to hold information about an active USB packet.  */ | ||||
| typedef enum USBPacketState { | ||||
|     USB_PACKET_UNDEFINED = 0, | ||||
|     USB_PACKET_SETUP, | ||||
|     USB_PACKET_ASYNC, | ||||
|     USB_PACKET_COMPLETE, | ||||
|     USB_PACKET_CANCELED, | ||||
| } USBPacketState; | ||||
| 
 | ||||
| struct USBPacket { | ||||
|     /* Data fields for use by the driver.  */ | ||||
|     int pid; | ||||
|     uint8_t devaddr; | ||||
|     uint8_t devep; | ||||
|     USBEndpoint *ep; | ||||
|     QEMUIOVector iov; | ||||
|     int result; /* transfer length or USB_RET_* status code */ | ||||
|     /* Internal use by the USB layer.  */ | ||||
|     USBEndpoint *owner; | ||||
|     USBPacketState state; | ||||
| }; | ||||
| 
 | ||||
| void usb_packet_init(USBPacket *p); | ||||
| @ -329,6 +337,11 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes); | ||||
| void usb_packet_skip(USBPacket *p, size_t bytes); | ||||
| void usb_packet_cleanup(USBPacket *p); | ||||
| 
 | ||||
| static inline bool usb_packet_is_inflight(USBPacket *p) | ||||
| { | ||||
|     return p->state == USB_PACKET_ASYNC; | ||||
| } | ||||
| 
 | ||||
| USBDevice *usb_find_device(USBPort *port, uint8_t addr); | ||||
| 
 | ||||
| int usb_handle_packet(USBDevice *dev, USBPacket *p); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gerd Hoffmann
						Gerd Hoffmann