usb: Fix usb_packet_map() in the presence of IOMMUs
authorDavid Gibson <david@gibson.dropbear.id.au>
Wed, 26 Sep 2012 02:59:31 +0000 (12:59 +1000)
committerGerd Hoffmann <kraxel@redhat.com>
Wed, 26 Sep 2012 07:24:42 +0000 (09:24 +0200)
commit39c138c8420f51a7da7b35233a8d7400a0b589ac
treeaaa8f11a1095f084741ce55b2dc3539e85864218
parent8b626aa7841ef79b70066c880b3b6c29496797af
usb: Fix usb_packet_map() in the presence of IOMMUs

With the IOMMU infrastructure introduced before 1.2, we need to use
dma_memory_map() to obtain a qemu pointer to memory from an IO bus address.
However, dma_memory_map() alters the given length to reflect the length
over which the used DMA translation is valid - which could be either more
or less than the requested length.

usb_packet_map() does not correctly handle these cases, simply failing if
dma_memory_map() alters the requested length.  If dma_memory_map()
increased the length, we just need to use the requested length for the
qemu_iovec_add().  However, if it decreased the length, it means that a
single DMA translation is not valid for the whole sglist element, and so
we need to loop, splitting it up into multiple iovec entries for each
piece with a DMA translation (in practice >2 pieces is unlikely).

This patch implements the correct behaviour

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
hw/usb/libhw.c