From e2f89926f19d2940eda070542501f39f51a8c81f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 27 Jun 2012 14:50:42 +1000 Subject: usb: Convert usb_packet_{map, unmap} to universal DMA helpers The USB UHCI and EHCI drivers were converted some time ago to use the pci_dma_*() helper functions. However, this conversion was not complete because in some places both these drivers do DMA via the usb_packet_map() function in usb-libhw.c. That function directly used cpu_physical_memory_map(). Now that the sglist code uses DMA wrappers properly, we can convert the functions in usb-libhw.c, thus conpleting the conversion of UHCI and EHCI to use the DMA wrappers. Note that usb_packet_map() invokes dma_memory_map() with a NULL invalidate callback function. When IOMMU support is added, this will mean that usb_packet_map() and the corresponding usb_packet_unmap() must be called in close proximity without dropping the qemu device lock - otherwise the guest might invalidate IOMMU mappings while they are still in use by the device code. Signed-off-by: David Gibson Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Anthony Liguori --- hw/usb/hcd-ehci.c | 4 ++-- hw/usb/hcd-uhci.c | 2 +- hw/usb/libhw.c | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'hw/usb') diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 6d2d54940d..1582c2c69e 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1426,8 +1426,8 @@ static void ehci_execute_complete(EHCIQueue *q) set_field(&q->qh.token, p->tbytes, QTD_TOKEN_TBYTES); } ehci_finish_transfer(q, p->usb_status); + usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); - usb_packet_unmap(&p->packet); q->qh.token ^= QTD_TOKEN_DTOGGLE; q->qh.token &= ~QTD_TOKEN_ACTIVE; @@ -1551,7 +1551,7 @@ static int ehci_process_itd(EHCIState *ehci, usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); assert(ret != USB_RET_ASYNC); - usb_packet_unmap(&ehci->ipacket); + usb_packet_unmap(&ehci->ipacket, &ehci->isgl); } else { DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); ret = USB_RET_NAK; diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 2ebce04b24..8f652d2f4a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -871,7 +871,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, done: len = uhci_complete_td(s, td, async, int_mask); - usb_packet_unmap(&async->packet); + usb_packet_unmap(&async->packet, &async->sgl); uhci_async_free(async); return len; } diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c index 2462351389..c0de30ea88 100644 --- a/hw/usb/libhw.c +++ b/hw/usb/libhw.c @@ -26,15 +26,15 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl) { - int is_write = (p->pid == USB_TOKEN_IN); - target_phys_addr_t len; + DMADirection dir = (p->pid == USB_TOKEN_IN) ? + DMA_DIRECTION_FROM_DEVICE : DMA_DIRECTION_TO_DEVICE; + dma_addr_t len; void *mem; int i; for (i = 0; i < sgl->nsg; i++) { len = sgl->sg[i].len; - mem = cpu_physical_memory_map(sgl->sg[i].base, &len, - is_write); + mem = dma_memory_map(sgl->dma, sgl->sg[i].base, &len, dir); if (!mem) { goto err; } @@ -46,18 +46,19 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl) return 0; err: - usb_packet_unmap(p); + usb_packet_unmap(p, sgl); return -1; } -void usb_packet_unmap(USBPacket *p) +void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl) { - int is_write = (p->pid == USB_TOKEN_IN); + DMADirection dir = (p->pid == USB_TOKEN_IN) ? + DMA_DIRECTION_FROM_DEVICE : DMA_DIRECTION_TO_DEVICE; int i; for (i = 0; i < p->iov.niov; i++) { - cpu_physical_memory_unmap(p->iov.iov[i].iov_base, - p->iov.iov[i].iov_len, is_write, - p->iov.iov[i].iov_len); + dma_memory_unmap(sgl->dma, p->iov.iov[i].iov_base, + p->iov.iov[i].iov_len, dir, + p->iov.iov[i].iov_len); } } -- cgit v1.2.1